//Copyright 2015 Erik De Rijcke
//
//Licensed under the Apache License,Version2.0(the"License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing,software
//distributed under the License is distributed on an"AS IS"BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package org.freedesktop.wayland.util;

import com.sun.jna.Pointer;

import java.util.HashMap;
import java.util.Map;

/**
 * A cache for POJOs with a native context.
 * It maps POJOs to their native context (a native pointer) so it can consistently return the same POJO given a pointer
 * value.
 */
public class ObjectCache {
    private static final Map<Pointer, Object> MAPPED_OBJECTS = new HashMap<Pointer, Object>();

    /**
     * Retrieve a POJO that is mapped to a native pointer. This method should be used to easily retrieve a POJO with a
     * native context. This method will only return a POJO if it was previously cached with a call to {@link #store(Pointer, Object)}
     *
     * @param pointer The pointer of the associated object.
     * @param <T>     The type of the POJO to cast.
     *
     * @return The cached object.
     */
    public static <T> T from(final Pointer pointer) {

        return (T) MAPPED_OBJECTS.get(pointer);
    }

    /**
     * Maps a native pointer to a POJO. This method should be used to easily store a POJO with a native context.
     *
     * @param pointer The pointer of the associated object.
     * @param object  The object to cache.
     */
    public static void store(final Pointer pointer,
                             final Object object) {
        final Object oldValue = MAPPED_OBJECTS.put(pointer,
                                                   object);
        if (oldValue != null) {
            //put it back!
            MAPPED_OBJECTS.put(pointer,
                               oldValue);
            throw new IllegalStateException(String.format("Can not re-map existing pointer. Pointer=%s, old value=%s, new value=%s",
                                                          pointer,
                                                          oldValue,
                                                          object));
        }
    }

    /**
     * Remove a mapped POJO. This method should be used when the native context of the POJO is no longer valid.
     *
     * @param pointer The pointer of the associated object.
     */
    public static <T> T remove(final Pointer pointer) {
        return (T) MAPPED_OBJECTS.remove(pointer);
    }
}

@@ -1878,84 +1878,715 @@
     
-final Object oldValue = MAPPED_OBJECTS.put(pointer,%0A                        
+//important notice:%0A        //A bug/missing feature in libwayland is that it does not allow us to fully track all library allocated objects (yet?).%0A        //As such there is no reliable way to be entirely sure when an object is really destroyed. As a side effect,%0A        //we can not guarantee that a newly stored object is not an erroneously mapped pointer or a 'wil-be-destroyed'%0A        //object and we have to simply map it 'as-is'. As a result, there is a memory leak that is: if we get a 'pre-destroy'%0A        //notify of object foo (=removes it from the object cache), and a subsequent call returns foo (=add it to the cache).%0A%0A        //final Object oldValue =%0A        MAPPED_OBJECTS.put(pointer,%0A
     
@@ -2625,16 +2625,18 @@
         
+//
 if (oldV
@@ -2659,20 +2659,16 @@
         
-   
- 
 //put it
@@ -2674,16 +2674,18 @@
 t back!%0A
+//
         
@@ -2708,32 +2708,34 @@
 TS.put(pointer,%0A
+//
                 
@@ -2760,16 +2760,18 @@
 Value);%0A
+//
         
@@ -2895,16 +2895,18 @@
 ue=%25s%22,%0A
+//
         
@@ -2956,32 +2956,34 @@
        pointer,%0A
+//
                 
@@ -3034,16 +3034,18 @@
 dValue,%0A
+//
         
@@ -3112,16 +3112,18 @@
         
+//
 %7D%0A    %7D%0A

disable checking for mapped objects in objectcache, as libwayland does not allow for full object lifecycle tracking.