ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [14/16] ignite git commit: IGNITE-1443: Implemented ContinuousQuery for C++
Date Wed, 21 Dec 2016 11:32:13 GMT
IGNITE-1443: Implemented ContinuousQuery for C++

This closes #1343


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/598b464f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/598b464f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/598b464f

Branch: refs/heads/ignite-2.0
Commit: 598b464f81d2e74dc0df62011e08f3a76a674db6
Parents: 700529a
Author: Igor Sapego <isapego@gridgain.com>
Authored: Tue Dec 20 19:38:41 2016 +0300
Committer: Pavel Tupitsyn <ptupitsyn@apache.org>
Committed: Tue Dec 20 19:38:41 2016 +0300

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 .../include/ignite/binary/binary_raw_reader.h   |  21 +
 .../ignite/impl/binary/binary_reader_impl.h     |   9 +-
 .../src/impl/binary/binary_reader_impl.cpp      |  17 +
 .../platforms/cpp/common/include/Makefile.am    |   5 +-
 .../common/include/ignite/common/concurrent.h   |  90 ++-
 .../include/ignite/common/reference_impl.h      | 286 +++++++++
 .../cpp/common/include/ignite/reference.h       | 564 +++++++++++++++++
 .../cpp/common/project/vs/common.vcxproj        |   2 +
 .../common/project/vs/common.vcxproj.filters    |   6 +
 modules/platforms/cpp/core-test/Makefile.am     |   7 +-
 .../core-test/config/cache-query-continuous.xml |  87 +++
 .../cpp/core-test/project/vs/core-test.vcxproj  |  10 +-
 .../project/vs/core-test.vcxproj.filters        |   6 +
 .../cpp/core-test/src/cache_query_test.cpp      |  76 +--
 .../cpp/core-test/src/continuous_query_test.cpp | 611 +++++++++++++++++++
 .../cpp/core-test/src/handle_registry_test.cpp  |  18 +-
 .../cpp/core-test/src/reference_test.cpp        | 412 +++++++++++++
 modules/platforms/cpp/core/Makefile.am          |   1 +
 .../cpp/core/include/ignite/cache/cache.h       | 104 +++-
 .../cpp/core/include/ignite/cache/cache_entry.h |  40 +-
 .../ignite/cache/event/cache_entry_event.h      | 139 +++++
 .../cache/event/cache_entry_event_listener.h    |  71 +++
 .../cache/query/continuous/continuous_query.h   | 239 ++++++++
 .../query/continuous/continuous_query_handle.h  | 133 ++++
 .../core/include/ignite/impl/cache/cache_impl.h | 116 +++-
 .../continuous/continuous_query_handle_impl.h   | 101 +++
 .../query/continuous/continuous_query_impl.h    | 351 +++++++++++
 .../core/include/ignite/impl/handle_registry.h  |  62 +-
 .../include/ignite/impl/ignite_environment.h    |  34 +-
 modules/platforms/cpp/core/namespaces.dox       |  74 ++-
 .../platforms/cpp/core/project/vs/core.vcxproj  |   7 +
 .../cpp/core/project/vs/core.vcxproj.filters    |  30 +
 .../cpp/core/src/impl/cache/cache_impl.cpp      |  31 +
 .../continuous/continuous_query_handle_impl.cpp |  96 +++
 .../cpp/core/src/impl/handle_registry.cpp       | 102 ++--
 .../cpp/core/src/impl/ignite_environment.cpp    |  98 ++-
 modules/platforms/cpp/examples/Makefile.am      |   1 +
 modules/platforms/cpp/examples/configure.ac     |   1 +
 .../continuous-query-example/Makefile.am        |  58 ++
 .../config/continuous-query-example.xml         |  52 ++
 .../project/vs/continuous-query-example.vcxproj | 110 ++++
 .../vs/continuous-query-example.vcxproj.filters |  35 ++
 .../src/continuous_query_example.cpp            | 142 +++++
 .../examples/include/ignite/examples/person.h   |   2 +-
 .../cpp/examples/project/vs/ignite-examples.sln |   6 +
 .../platforms/cpp/jni/include/ignite/jni/java.h |   2 +-
 modules/platforms/cpp/jni/src/java.cpp          |   4 +-
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |   4 +-
 modules/platforms/cpp/project/vs/ignite.slnrel  |   3 +
 .../platforms/cpp/project/vs/ignite_x86.slnrel  |   3 +
 51 files changed, 4216 insertions(+), 264 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index b534eb7..db6128e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ git-patch-prop-local.sh
 *.opensdf
 *.db
 *.opendb
+.vs
 ipch/
 [Oo]bj/
 [Bb]in

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
index 72aab55..d15848b 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
@@ -398,6 +398,27 @@ namespace ignite
             {
                 return impl->ReadObject<T>();
             }
+
+            /**
+             * Try read object.
+             * Reads value, stores it to res and returns true if the value is
+             * not null. Otherwise just returns false.
+             *
+             * @param res Read value is placed here if non-null.
+             * @return True if the non-null value has been read and false
+             *     otherwise.
+             */
+            template<typename T>
+            bool TryReadObject(T& res)
+            {
+                if (impl->SkipIfNull())
+                    return false;
+
+                res = impl->ReadObject<T>();
+
+                return true;
+            }
+
         private:
             /** Implementation delegate. */
             ignite::impl::binary::BinaryReaderImpl* impl;  

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
index 8c4b464..cd32203 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
@@ -723,6 +723,13 @@ namespace ignite
                 bool HasNextElement(int32_t id) const;
 
                 /**
+                 * Skip next value if it is the null.
+                 *
+                 * @return True if the null value has been detected and skipped.
+                 */
+                bool SkipIfNull();
+
+                /**
                  * Read element.
                  *
                  * @param id Session ID.
@@ -763,7 +770,7 @@ namespace ignite
                     *key = ReadTopObject<K>();
                     *val = ReadTopObject<V>();
                 }
-                
+
                 /**
                  * Read object.
                  *

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
index fb75ba5..c128df6 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
@@ -663,6 +663,23 @@ namespace ignite
                 return elemId == id && elemRead < elemCnt;
             }
 
+            bool BinaryReaderImpl::SkipIfNull()
+            {
+                CheckRawMode(true);
+                CheckSingleMode(true);
+
+                InteropStreamPositionGuard<InteropInputStream> positionGuard(*stream);
+
+                int8_t hdr = stream->ReadInt8();
+
+                if (hdr != IGNITE_HDR_NULL)
+                    return false;
+
+                positionGuard.Release();
+
+                return true;
+            }
+
             void BinaryReaderImpl::SetRawMode()
             {
                 CheckRawMode(false);

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/Makefile.am b/modules/platforms/cpp/common/include/Makefile.am
index 2e53608..a5073f6 100644
--- a/modules/platforms/cpp/common/include/Makefile.am
+++ b/modules/platforms/cpp/common/include/Makefile.am
@@ -23,14 +23,15 @@ nobase_include_HEADERS = \
 	ignite/common/concurrent.h \
 	ignite/common/decimal.h \
 	ignite/common/default_allocator.h \
+	ignite/common/reference_impl.h \
 	ignite/common/dynamic_size_array.h \
 	ignite/common/fixed_size_array.h \
 	ignite/common/utils.h \
 	ignite/date.h \
 	ignite/guid.h \
 	ignite/ignite_error.h \
-	ignite/timestamp.h
-	ignite/timestamp.h
+	ignite/timestamp.h \
+	ignite/reference.h
 
 uninstall-hook:
 	if [ -d ${includedir}/ignite ]; then find ${includedir}/ignite -type d -empty -delete; fi

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/common/concurrent.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/concurrent.h b/modules/platforms/cpp/common/include/ignite/common/concurrent.h
index 35c2209..ff0e54a 100644
--- a/modules/platforms/cpp/common/include/ignite/common/concurrent.h
+++ b/modules/platforms/cpp/common/include/ignite/common/concurrent.h
@@ -19,6 +19,7 @@
 #define _IGNITE_COMMON_CONCURRENT
 
 #include <cassert>
+#include <utility>
 
 #include "ignite/common/concurrent_os.h"
 
@@ -121,10 +122,15 @@ namespace ignite
             public:
                 friend class EnableSharedFromThis<T>;
 
+                template<typename T2>
+                friend class SharedPointer;
+
                 /**
                  * Constructor.
                  */
-                SharedPointer() : impl(0)
+                SharedPointer() :
+                    ptr(0),
+                    impl(0)
                 {
                     // No-op.
                 }
@@ -133,17 +139,17 @@ namespace ignite
                  * Constructor.
                  *
                  * @param ptr Raw pointer.
+                 * @param deleter Delete function.
                  */
-                explicit SharedPointer(T* ptr)
+                SharedPointer(T* ptr, void(*deleter)(T*) = &SharedPointerDefaultDeleter<T>) :
+                    ptr(ptr),
+                    impl(0)
                 {
                     if (ptr)
                     {
-                        void(*deleter)(T*) = (void(*)(T*)) &SharedPointerDefaultDeleter<T>;
                         impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter));
                         ImplEnableShared(ptr, impl);
                     }
-                    else
-                        impl = 0;
                 }
 
                 /**
@@ -152,15 +158,16 @@ namespace ignite
                  * @param ptr Raw pointer.
                  * @param deleter Delete function.
                  */
-                SharedPointer(T* ptr, void(*deleter)(T*))
+                template<typename T2>
+                SharedPointer(T2* ptr, void(*deleter)(T2*) = &SharedPointerDefaultDeleter<T2>) :
+                    ptr(ptr),
+                    impl(0)
                 {
                     if (ptr)
                     {
                         impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter));
                         ImplEnableShared(ptr, impl);
                     }
-                    else
-                        impl = 0;
                 }
 
                 /**
@@ -169,6 +176,21 @@ namespace ignite
                  * @param other Instance to copy.
                  */
                 SharedPointer(const SharedPointer& other) :
+                    ptr(other.ptr),
+                    impl(other.impl)
+                {
+                    if (impl)
+                        impl->Increment();
+                }
+
+                /**
+                 * Copy constructor.
+                 *
+                 * @param other Instance to copy.
+                 */
+                template<typename T2>
+                SharedPointer(const SharedPointer<T2>& other) :
+                    ptr(other.ptr),
                     impl(other.impl)
                 {
                     if (impl)
@@ -186,26 +208,43 @@ namespace ignite
                     {
                         SharedPointer tmp(other);
 
-                        std::swap(impl, tmp.impl);
+                        Swap(tmp);
                     }
 
                     return *this;
                 }
 
                 /**
+                 * Assignment operator.
+                 *
+                 * @param other Other instance.
+                 */
+                template<typename T2>
+                SharedPointer& operator=(const SharedPointer<T2>& other)
+                {
+                    SharedPointer<T> tmp(other);
+
+                    Swap(tmp);
+
+                    return *this;
+                }
+
+                /**
                  * Destructor.
                  */
                 ~SharedPointer()
                 {
                     if (impl && impl->Decrement())
                     {
-                        T* ptr = Get();
+                        void* ptr0 = impl->Pointer();
 
-                        void(*deleter)(T*) = reinterpret_cast<void(*)(T*)>(impl->Deleter());
+                        void(*deleter)(void*) = impl->Deleter();
 
-                        deleter(ptr);
+                        deleter(ptr0);
 
                         delete impl;
+
+                        ptr = 0;
                     }
                 }
 
@@ -216,7 +255,7 @@ namespace ignite
                  */
                 T* Get()
                 {
-                    return impl ? static_cast<T*>(impl->Pointer()) : 0;
+                    return ptr;
                 }
 
                 /**
@@ -226,7 +265,7 @@ namespace ignite
                  */
                 const T* Get() const
                 {
-                    return impl ? static_cast<T*>(impl->Pointer()) : 0;
+                    return ptr;
                 }
 
                 /**
@@ -245,7 +284,30 @@ namespace ignite
                     return impl != 0;
                 }
 
+                /**
+                 * Swap pointer content with another instance.
+                 *
+                 * @param other Other instance.
+                 */
+                void Swap(SharedPointer& other)
+                {
+                    if (this != &other)
+                    {
+                        T* ptrTmp = ptr;
+                        SharedPointerImpl* implTmp = impl;
+
+                        ptr = other.ptr;
+                        impl = other.impl;
+
+                        other.ptr = ptrTmp;
+                        other.impl = implTmp;
+                    }
+                }
+
             private:
+                /* Pointer. */
+                T* ptr;
+
                 /** Implementation. */
                 SharedPointerImpl* impl;
             };

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/common/reference_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/reference_impl.h b/modules/platforms/cpp/common/include/ignite/common/reference_impl.h
new file mode 100644
index 0000000..e38da8c
--- /dev/null
+++ b/modules/platforms/cpp/common/include/ignite/common/reference_impl.h
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.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.
+ */
+
+/**
+ * @file
+ * Declares ignite::ReferenceImplBase class and its implementations.
+ */
+
+#ifndef _IGNITE_COMMON_REFERENCE_IMPL
+#define _IGNITE_COMMON_REFERENCE_IMPL
+
+#include <utility>
+
+#include <ignite/common/common.h>
+
+namespace ignite
+{
+    namespace common
+    {
+        // Any number is good as long as it is not null.
+        enum { POINTER_CAST_MAGIC_NUMBER = 80000 };
+
+        /**
+         * Interface for constant Reference implementation class template.
+         */
+        class ConstReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ConstReferenceImplBase()
+            {
+                // No-op.
+            }
+
+            /**
+             * Get the constant pointer.
+             *
+             * @return Constant pointer to underlying value.
+             */
+            virtual const void* Get() const = 0;
+        };
+
+        /**
+         * Interface for Reference implementation class template.
+         */
+        class ReferenceImplBase : public ConstReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ReferenceImplBase()
+            {
+                // No-op.
+            }
+
+            virtual const void* Get() const = 0;
+
+            /**
+             * Get the pointer.
+             *
+             * @return Pointer to underlying value.
+             */
+            virtual void* Get() = 0;
+        };
+
+        /**
+         * Reference class implementation for smart pointers.
+         *
+         * Note, this class does not implement any smart pointer functionality
+         * itself, instead it wraps one of the existing wide-spread smart
+         * pointer implementations and provides unified interface for them.
+         */
+        template<typename P>
+        class ReferenceSmartPointer : public ReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ReferenceSmartPointer()
+            {
+                // No-op.
+            }
+
+            /**
+             * Default constructor.
+             */
+            ReferenceSmartPointer() :
+                ptr()
+            {
+                // No-op.
+            }
+
+            virtual const void* Get() const
+            {
+                return reinterpret_cast<const void*>(&(*ptr));
+            }
+
+            virtual void* Get()
+            {
+                return reinterpret_cast<void*>(&(*ptr));
+            }
+
+            /**
+             * Swap underlying smart pointer.
+             *
+             * @param other Another instance.
+             */
+            void Swap(P& other)
+            {
+                using std::swap;
+
+                swap(ptr, other);
+            }
+
+        private:
+            /** Underlying pointer. */
+            P ptr;
+        };
+
+        /**
+         * Reference implementation for the owning raw pointer.
+         */
+        template<typename T>
+        class ReferenceOwningRawPointer : public ReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ReferenceOwningRawPointer()
+            {
+                delete ptr;
+            }
+
+            /**
+             * Default constructor.
+             */
+            ReferenceOwningRawPointer() :
+                ptr(0)
+            {
+                // No-op.
+            }
+
+            /**
+             * Pointer constructor.
+             *
+             * @param ptr Pointer to take ownership over.
+             */
+            ReferenceOwningRawPointer(T* ptr) :
+                ptr(ptr)
+            {
+                // No-op.
+            }
+
+            virtual const void* Get() const
+            {
+                return reinterpret_cast<const void*>(ptr);
+            }
+
+            virtual void* Get()
+            {
+                return reinterpret_cast<void*>(ptr);
+            }
+
+        private:
+            /** Underlying pointer. */
+            T* ptr;
+        };
+
+        /**
+         * Reference implementation for the raw pointer.
+         */
+        template<typename T>
+        class ReferenceNonOwningRawPointer : public ReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ReferenceNonOwningRawPointer()
+            {
+                // No-op.
+            }
+
+            /**
+             * Default constructor.
+             */
+            ReferenceNonOwningRawPointer() :
+                ptr(0)
+            {
+                // No-op.
+            }
+
+            /**
+             * Pointer constructor.
+             *
+             * @param ptr Pointer.
+             */
+            ReferenceNonOwningRawPointer(T* ptr) :
+                ptr(ptr)
+            {
+                // No-op.
+            }
+
+            virtual const void* Get() const
+            {
+                return reinterpret_cast<const void*>(ptr);
+            }
+
+            virtual void* Get()
+            {
+                return reinterpret_cast<void*>(ptr);
+            }
+
+        private:
+            /** Underlying pointer. */
+            T* ptr;
+        };
+
+        /**
+         * Constant reference implementation for the raw pointer.
+         */
+        template<typename T>
+        class ConstReferenceNonOwningRawPointer : public ConstReferenceImplBase
+        {
+        public:
+            /**
+             * Destructor.
+             */
+            virtual ~ConstReferenceNonOwningRawPointer()
+            {
+                // No-op.
+            }
+
+            /**
+             * Default constructor.
+             */
+            ConstReferenceNonOwningRawPointer() :
+                ptr(0)
+            {
+                // No-op.
+            }
+
+            /**
+             * Pointer constructor.
+             *
+             * @param ptr Pointer.
+             */
+            ConstReferenceNonOwningRawPointer(const T* ptr) :
+                ptr(ptr)
+            {
+                // No-op.
+            }
+
+            virtual const void* Get() const
+            {
+                return reinterpret_cast<const void*>(ptr);
+            }
+
+        private:
+            /** Underlying pointer. */
+            const T* ptr;
+        };
+
+    }
+}
+
+#endif //_IGNITE_COMMON_REFERENCE_IMPL
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/reference.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/reference.h b/modules/platforms/cpp/common/include/ignite/reference.h
new file mode 100644
index 0000000..b026ad7
--- /dev/null
+++ b/modules/platforms/cpp/common/include/ignite/reference.h
@@ -0,0 +1,564 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.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.
+ */
+
+/**
+ * @file
+ * Declares ignite::Reference class.
+ */
+
+#ifndef _IGNITE_COMMON_REFERENCE
+#define _IGNITE_COMMON_REFERENCE
+
+#include <cstddef>
+
+#include <ignite/common/common.h>
+#include <ignite/common/concurrent.h>
+#include <ignite/common/reference_impl.h>
+
+namespace ignite
+{
+    template<typename T>
+    class Reference;
+
+    /**
+     * Constant Reference class.
+     *
+     * Abstraction on any reference-type object, from simple raw pointers and
+     * references to standard library smart pointers. Provides only constant
+     * access to the underlying data.
+     *
+     * There are no requirements for the template type T.
+     */
+    template<typename T>
+    class ConstReference
+    {
+        template<typename>
+        friend class ConstReference;
+
+        template<typename>
+        friend class Reference;
+
+    public:
+        /**
+         * Default constructor.
+         */
+        ConstReference() :
+            ptr(),
+            offset(0)
+        {
+            // No-op.
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param ptr ConstReference class implementation.
+         * @param offset Pointer offset.
+         */
+        explicit ConstReference(common::ConstReferenceImplBase* ptr, ptrdiff_t offset = 0) :
+            ptr(ptr),
+            offset(offset)
+        {
+            // No-op.
+        }
+
+        /**
+         * Copy constructor.
+         *
+         * @param other Another instance.
+         */
+        ConstReference(const ConstReference& other) :
+            ptr(other.ptr),
+            offset(other.offset)
+        {
+            // No-op.
+        }
+
+        /**
+         * Copy constructor.
+         *
+         * Constant reference of type T2 should be static-castable to constant
+         * reference of type T.
+         *
+         * @param other Another instance.
+         */
+        template<typename T2>
+        ConstReference(const ConstReference<T2>& other) :
+            ptr(other.ptr),
+            offset(other.offset)
+        {
+            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
+            T* p1 = static_cast<T*>(p0);
+
+            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
+            offset += diff;
+        }
+
+        /**
+         * Assignment operator.
+         *
+         * @param other Another instance.
+         */
+        ConstReference& operator=(const ConstReference& other)
+        {
+            ptr = other.ptr;
+            offset = other.offset;
+
+            return *this;
+        }
+        
+        /**
+         * Assignment operator.
+         *
+         * Constant reference of type T2 should be static-castable to constant
+         * reference of type T.
+         *
+         * @param other Another instance.
+         */
+        template<typename T2>
+        ConstReference& operator=(const ConstReference<T2>& other)
+        {
+            ptr = other.ptr;
+            offset = other.offset;
+
+            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
+            T* p1 = static_cast<T*>(p0);
+
+            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
+            offset += diff;
+
+            return *this;
+        }
+
+        /**
+         * Destructor.
+         */
+        ~ConstReference()
+        {
+            // No-op.
+        }
+
+        /**
+         * Dereference the pointer.
+         *
+         * If the pointer is null then this operation causes undefined
+         * behaviour.
+         *
+         * @return Constant reference to underlying value.
+         */
+        const T& Get() const
+        {
+            return *reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
+        }
+
+        /**
+         * Check if the pointer is null.
+         *
+         * @return True if the value is null.
+         */
+        bool IsNull() const
+        {
+            const common::ConstReferenceImplBase* raw = ptr.Get();
+
+            return !raw || !raw->Get();
+        }
+
+    private:
+        /** Implementation. */
+        common::concurrent::SharedPointer<common::ConstReferenceImplBase> ptr;
+
+        /** Address offset. */
+        ptrdiff_t offset;
+    };
+
+    /**
+     * Reference class.
+     *
+     * Abstraction on any reference-type object, from simple raw pointers and
+     * references to standard library smart pointers.
+     *
+     * There are no requirements for the template type T.
+     */
+    template<typename T>
+    class Reference
+    {
+        template<typename>
+        friend class Reference;
+    public:
+        /**
+         * Default constructor.
+         */
+        Reference() :
+            ptr(),
+            offset(0)
+        {
+            // No-op.
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param ptr Reference class implementation.
+         * @param offset Pointer offset.
+         */
+        explicit Reference(common::ReferenceImplBase* ptr, ptrdiff_t offset = 0) :
+            ptr(ptr),
+            offset(offset)
+        {
+            // No-op.
+        }
+
+        /**
+         * Copy constructor.
+         *
+         * @param other Another instance.
+         */
+        Reference(const Reference& other) :
+            ptr(other.ptr),
+            offset(other.offset)
+        {
+            // No-op.
+        }
+
+        /**
+         * Copy constructor.
+         * 
+         * Reference of type T2 should be static-castable to reference of type T.
+         *
+         * @param other Another instance.
+         */
+        template<typename T2>
+        Reference(const Reference<T2>& other) :
+            ptr(other.ptr),
+            offset(other.offset)
+        {
+            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
+            T* p1 = static_cast<T*>(p0);
+
+            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
+            offset += diff;
+        }
+
+        /**
+         * Assignment operator.
+         *
+         * @param other Another instance.
+         */
+        Reference& operator=(const Reference& other)
+        {
+            ptr = other.ptr;
+            offset = other.offset;
+
+            return *this;
+        }
+        
+        /**
+         * Assignment operator.
+         *
+         * Reference of type T2 should be static-castable to reference of type T.
+         *
+         * @param other Another instance.
+         */
+        template<typename T2>
+        Reference& operator=(const Reference<T2>& other)
+        {
+            ptr = other.ptr;
+            offset = other.offset;
+
+            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
+            T* p1 = static_cast<T*>(p0);
+
+            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
+            offset += diff;
+
+            return *this;
+        }
+
+        /**
+         * Destructor.
+         */
+        ~Reference()
+        {
+            // No-op.
+        }
+
+        /**
+         * Const cast operator.
+         *
+         * Reference of type T2 should be static-castable to reference of type T.
+         *
+         * Casts this instance to constant reference.
+         */
+        template<typename T2>
+        operator ConstReference<T2>()
+        {
+            ConstReference<T2> cr;
+
+            cr.ptr = ptr;
+            cr.offset = offset;
+
+            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
+            const T* p1 = static_cast<T*>(p0);
+
+            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
+            cr.offset -= diff;
+
+            return cr;
+        }
+
+        /**
+         * Dereference the pointer.
+         *
+         * If the pointer is null then this operation causes undefined
+         * behaviour.
+         *
+         * @return Constant reference to underlying value.
+         */
+        const T& Get() const
+        {
+            return *reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
+        }
+
+        /**
+         * Dereference the pointer.
+         *
+         * If the pointer is null then this operation causes undefined
+         * behaviour.
+         *
+         * @return Reference to underlying value.
+         */
+        T& Get()
+        {
+            return *reinterpret_cast<T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
+        }
+
+        /**
+         * Check if the pointer is null.
+         *
+         * @return True if the value is null.
+         */
+        bool IsNull() const
+        {
+            const common::ReferenceImplBase* raw = ptr.Get();
+
+            return !raw || !raw->Get();
+        }
+
+    private:
+        /** Implementation. */
+        common::concurrent::SharedPointer<common::ReferenceImplBase> ptr;
+
+        /** Address offset. */
+        ptrdiff_t offset;
+    };
+
+    /**
+     * Make ignite::Reference instance out of smart pointer.
+     *
+     * Template type 'T' should be a smart pointer and provide pointer semantics:
+     * - There should be defined type 'T::element_type', showing underlying type.
+     * - Type 'T' should be dereferencible (should have operators
+     *   T::element_type& operator*() and const T::element_type& operator*() const).
+     * - Operation std::swap should result in valid result if applied to two
+     *   instances of that type.
+     *
+     * @param ptr Pointer.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    Reference<typename T::element_type> MakeReferenceFromSmartPointer(T ptr)
+    {
+        common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>();
+
+        Reference<typename T::element_type> res(impl);
+
+        impl->Swap(ptr);
+
+        return res;
+    }
+
+    /**
+     * Make ignite::ConstReference instance out of smart pointer.
+     *
+     * Template type 'T' should be a smart pointer and provide pointer semantics:
+     * - There should be defined type 'T::element_type', showing underlying type.
+     * - Type 'T' should be dereferencible (should have operators
+     *   T::element_type& operator*() and const T::element_type& operator*() const).
+     * - Operation std::swap should result in valid result if applied to two
+     *   instances of that type.
+     *
+     * @param ptr Pointer.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    ConstReference<typename T::element_type> MakeConstReferenceFromSmartPointer(T ptr)
+    {
+        common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>();
+
+        ConstReference<typename T::element_type> res(impl);
+
+        impl->Swap(ptr);
+
+        return res;
+    }
+
+    /**
+     * Copy object and wrap it to make ignite::Reference instance.
+     *
+     * Template type 'T' should be copy-constructible.
+     *
+     * @param val Instance.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    Reference<T> MakeReferenceFromCopy(const T& val)
+    {
+        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val));
+
+        return Reference<T>(impl);
+    }
+
+    /**
+     * Copy object and wrap it to make ignite::ConstReference instance.
+     *
+     * Template type 'T' should be copy-constructible.
+     *
+     * @param val Instance.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    ConstReference<T> MakeConstReferenceFromCopy(const T& val)
+    {
+        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val));
+
+        return ConstReference<T>(impl);
+    }
+
+    /**
+     * Make ignite::Reference instance out of pointer and pass its ownership.
+     * Passed object deleted by Ignite when no longer needed.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Instance.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    Reference<T> MakeReferenceFromOwningPointer(T* val)
+    {
+        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val);
+
+        return Reference<T>(impl);
+    }
+
+    /**
+     * Make ignite::ConstReference instance out of pointer and pass its ownership.
+     * Passed object deleted by Ignite when no longer needed.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Instance.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    ConstReference<T> MakeConstReferenceFromOwningPointer(T* val)
+    {
+        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val);
+
+        return ConstReference<T>(impl);
+    }
+
+    /**
+     * Make ignite::Reference instance out of reference.
+     * Ignite do not manage passed object and does not affect its lifetime.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Reference.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    Reference<T> MakeReference(T& val)
+    {
+        common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(&val);
+
+        return Reference<T>(impl);
+    }
+
+    /**
+     * Make ignite::Reference instance out of pointer.
+     * Ignite do not manage passed object and does not affect its lifetime.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Reference.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    Reference<T> MakeReference(T* val)
+    {
+        common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(val);
+
+        return Reference<T>(impl);
+    }
+
+    /**
+     * Make ignite::ConstReference instance out of constant reference.
+     * Ignite do not manage passed object and does not affect its lifetime.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Reference.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    ConstReference<T> MakeConstReference(const T& val)
+    {
+        common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(&val);
+
+        return ConstReference<T>(impl);
+    }
+
+    /**
+     * Make ignite::ConstReference instance out of constant pointer.
+     * Ignite do not manage passed object and does not affect its lifetime.
+     *
+     * There are no requirements for the template type T.
+     *
+     * @param val Reference.
+     * @return Implementation defined value. User should not explicitly use the
+     *     returned value.
+     */
+    template<typename T>
+    ConstReference<T> MakeConstReference(const T* val)
+    {
+        common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(val);
+
+        return ConstReference<T>(impl);
+    }
+}
+
+#endif //_IGNITE_COMMON_REFERENCE
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/project/vs/common.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj b/modules/platforms/cpp/common/project/vs/common.vcxproj
index 149fa48..99fd551 100644
--- a/modules/platforms/cpp/common/project/vs/common.vcxproj
+++ b/modules/platforms/cpp/common/project/vs/common.vcxproj
@@ -171,10 +171,12 @@
     <ClInclude Include="..\..\include\ignite\common\dynamic_size_array.h" />
     <ClInclude Include="..\..\include\ignite\common\fixed_size_array.h" />
     <ClInclude Include="..\..\include\ignite\common\bits.h" />
+    <ClInclude Include="..\..\include\ignite\common\reference_impl.h" />
     <ClInclude Include="..\..\include\ignite\common\utils.h" />
     <ClInclude Include="..\..\include\ignite\date.h" />
     <ClInclude Include="..\..\include\ignite\guid.h" />
     <ClInclude Include="..\..\include\ignite\ignite_error.h" />
+    <ClInclude Include="..\..\include\ignite\reference.h" />
     <ClInclude Include="..\..\include\ignite\timestamp.h" />
     <ClInclude Include="..\..\os\win\include\ignite\common\common.h" />
     <ClInclude Include="..\..\os\win\include\ignite\common\concurrent_os.h" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
index ae17daf..d99722b 100644
--- a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
+++ b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
@@ -58,6 +58,12 @@
     <ClInclude Include="..\..\include\ignite\common\decimal.h">
       <Filter>Code\common</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ignite\common\reference_impl.h">
+      <Filter>Code\common</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\reference.h">
+      <Filter>Code</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\date.cpp">

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/Makefile.am b/modules/platforms/cpp/core-test/Makefile.am
index 42680cd..3cf1d0e 100644
--- a/modules/platforms/cpp/core-test/Makefile.am
+++ b/modules/platforms/cpp/core-test/Makefile.am
@@ -43,15 +43,20 @@ AM_CXXFLAGS = \
 
 ignite_tests_LDADD = \
     @top_srcdir@/core/libignite.la \
-    -lpthread
+    -lpthread \
+    -lboost_thread \
+    -lboost_system \
+    -lboost_chrono
 
 ignite_tests_LDFLAGS = \
     -static-libtool-libs
 
 ignite_tests_SOURCES = \
+    src/reference_test.cpp \
     src/bits_test.cpp \
     src/cache_test.cpp \
     src/cache_query_test.cpp \
+    src/continuous_query_test.cpp \
     src/concurrent_test.cpp \
     src/ignition_test.cpp \
     src/interop_memory_test.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/config/cache-query-continuous.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/config/cache-query-continuous.xml b/modules/platforms/cpp/core-test/config/cache-query-continuous.xml
new file mode 100644
index 0000000..1b940fd
--- /dev/null
+++ b/modules/platforms/cpp/core-test/config/cache-query-continuous.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
+
+        <property name="cacheConfiguration">
+            <list>
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="transactional_no_backup"/>
+                    <property name="cacheMode" value="PARTITIONED"/>
+                    <property name="atomicityMode" value="TRANSACTIONAL"/>
+                    <property name="writeSynchronizationMode" value="FULL_SYNC"/>
+                    <property name="backups" value="0"/>
+                    <property name="startSize" value="10"/>
+                    <property name="queryEntities">
+                        <list>
+                            <bean class="org.apache.ignite.cache.QueryEntity">
+                                <property name="keyType" value="java.lang.Integer"/>
+                                <property name="valueType" value="TestEntry"/>
+
+                                <property name="fields">
+                                    <map>
+                                        <entry key="value" value="java.lang.Integer"/>
+                                    </map>
+                                </property>
+
+                                <property name="indexes">
+                                    <list>
+                                        <bean class="org.apache.ignite.cache.QueryIndex">
+                                            <property name="fields">
+                                                <map>
+                                                    <entry key="value" value="true"/>
+                                                </map>
+                                            </property>
+                                            <property name="indexType" value="FULLTEXT"/>
+                                        </bean>
+                                    </list>
+                                </property>
+                            </bean>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host IP address. -->
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+                <property name="socketTimeout" value="300" />
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
index 6f13719..a41d8f8 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
@@ -43,6 +43,7 @@
     <ClCompile Include="..\..\src\decimal_test.cpp" />
     <ClCompile Include="..\..\src\dynamic_size_array_test.cpp" />
     <ClCompile Include="..\..\src\fixed_size_array_test.cpp" />
+    <ClCompile Include="..\..\src\continuous_query_test.cpp" />
     <ClCompile Include="..\..\src\ignite_error_test.cpp" />
     <ClCompile Include="..\..\src\ignition_test.cpp" />
     <ClCompile Include="..\..\src\handle_registry_test.cpp" />
@@ -54,6 +55,7 @@
     <ClCompile Include="..\..\src\interop_memory_test.cpp" />
     <ClCompile Include="..\..\src\interop_test.cpp" />
     <ClCompile Include="..\..\src\bits_test.cpp" />
+    <ClCompile Include="..\..\src\reference_test.cpp" />
     <ClCompile Include="..\..\src\teamcity_boost.cpp" />
     <ClCompile Include="..\..\src\teamcity_messages.cpp" />
     <ClCompile Include="..\..\src\transactions_test.cpp" />
@@ -129,7 +131,7 @@
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Console</SubSystem>
     </Link>
   </ItemDefinitionGroup>
@@ -144,7 +146,7 @@
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -162,7 +164,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -180,7 +182,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
index cf1aaca..a95e3a4 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
@@ -58,6 +58,12 @@
     <ClCompile Include="..\..\src\interop_test.cpp">
       <Filter>Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\continuous_query_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\reference_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\teamcity_messages.h">

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/cache_query_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/cache_query_test.cpp b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
index c1c26ac..928d29e 100644
--- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp
+++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
@@ -232,8 +232,6 @@ private:
     int32_t someVal;
 };
 
-
-
 namespace ignite
 {
     namespace binary
@@ -296,74 +294,6 @@ namespace ignite
     }
 }
 
-///**
-// * Test setup fixture.
-// */
-//struct CacheQueryTestSuiteFixture
-//{
-//    Ignite StartNode(const char* name)
-//    {
-//        IgniteConfiguration cfg;
-//
-//        cfg.jvmOpts.push_back("-Xdebug");
-//        cfg.jvmOpts.push_back("-Xnoagent");
-//        cfg.jvmOpts.push_back("-Djava.compiler=NONE");
-//        cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005");
-//        cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError");
-//
-//#ifdef IGNITE_TESTS_32
-//        cfg.jvmInitMem = 256;
-//        cfg.jvmMaxMem = 768;
-//#else
-//        cfg.jvmInitMem = 1024;
-//        cfg.jvmMaxMem = 4096;
-//#endif
-//
-//        cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml");
-//
-//        IgniteError err;
-//
-//        Ignite grid0 = Ignition::Start(cfg, name, &err);
-//
-//        if (err.GetCode() != IgniteError::IGNITE_SUCCESS)
-//            BOOST_ERROR(err.GetText());
-//
-//        return grid0;
-//    }
-//
-//
-//    /**
-//     * Constructor.
-//     */
-//    CacheQueryTestSuiteFixture() : 
-//        grid(StartNode("Node1"))
-//    {
-//        // No-op.
-//    }
-//
-//    /**
-//     * Destructor.
-//     */
-//    ~CacheQueryTestSuiteFixture()
-//    {
-//        Ignition::StopAll(true);
-//    }
-//
-//    /** Person cache accessor. */
-//    Cache<int, QueryPerson> GetPersonCache()
-//    {
-//        return grid.GetCache<int, QueryPerson>("QueryPerson");
-//    }
-//
-    ///** Relation cache accessor. */
-    //Cache<int, QueryRelation> GetRelationCache()
-    //{
-    //    return grid.GetCache<int, QueryRelation>("QueryRelation");
-    //}
-//
-//    /** Node started during the test. */
-//    Ignite grid;
-//};
 
 /**
  * Count number of records returned by cursor.
@@ -677,7 +607,11 @@ struct CacheQueryTestSuiteFixture
         cfg.jvmMaxMem = 4096;
 #endif
 
-        cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml");
+        const char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH");
+
+        BOOST_CHECK(cfgPath != 0);
+
+        cfg.springCfgPath.assign(cfgPath).append("/cache-query.xml");
 
         IgniteError err;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/continuous_query_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/continuous_query_test.cpp b/modules/platforms/cpp/core-test/src/continuous_query_test.cpp
new file mode 100644
index 0000000..e9d7e8a
--- /dev/null
+++ b/modules/platforms/cpp/core-test/src/continuous_query_test.cpp
@@ -0,0 +1,611 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.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.
+ */
+
+#ifndef _MSC_VER
+    #define BOOST_TEST_DYN_LINK
+#endif
+
+#include <deque>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/optional.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+#include "ignite/ignition.h"
+#include "ignite/cache/cache.h"
+
+using namespace ignite;
+using namespace ignite::cache;
+using namespace ignite::cache::event;
+using namespace ignite::cache::query;
+using namespace ignite::cache::query::continuous;
+using namespace boost::unit_test;
+
+/**
+ * Very simple concurrent queue implementation.
+ */
+template<typename T>
+class ConcurrentQueue
+{
+public:
+    /*
+     * Constructor.
+     */
+    ConcurrentQueue()
+    {
+        // No-op.
+    }
+
+    /*
+     * Push next element to queue.
+     *
+     * @param val Value to push.
+     */
+    void Push(const T& val)
+    {
+        boost::unique_lock<boost::mutex> guard(mutex);
+
+        queue.push_back(val);
+
+        cv.notify_one();
+    }
+
+    /*
+     * Pull element from the queue with the specified timeout.
+     *
+     * @param val Value is placed there on success.
+     * @param timeout Timeout.
+     * @return True on success and false on timeout.
+     */
+    template <typename Rep, typename Period>
+    bool Pull(T& val, const boost::chrono::duration<Rep, Period>& timeout)
+    {
+        boost::unique_lock<boost::mutex> guard(mutex);
+
+        if (queue.empty())
+        {
+            boost::cv_status res = cv.wait_for(guard, timeout);
+
+            if (res == boost::cv_status::timeout)
+                return false;
+        }
+
+        assert(!queue.empty());
+
+        val = queue.front();
+
+        queue.pop_front();
+
+        return true;
+    }
+
+private:
+    boost::mutex mutex;
+
+    boost::condition_variable cv;
+
+    std::deque<T> queue;
+};
+
+/*
+ * Test listener class. Stores events it has been notified about in concurrent
+ * queue so they can be checked later.
+ */
+template<typename K, typename V>
+class Listener : public CacheEntryEventListener<K, V>
+{
+public:
+    /*
+     * Default constructor.
+     */
+    Listener()
+    {
+        // No-op.
+    }
+
+    /**
+     * Event callback.
+     *
+     * @param evts Events.
+     * @param num Events number.
+     */
+    virtual void OnEvent(const CacheEntryEvent<K, V>* evts, uint32_t num)
+    {
+        for (uint32_t i = 0; i < num; ++i)
+            eventQueue.Push(evts[i]);
+    }
+
+    /*
+     * Check that next received event contains specific values.
+     *
+     * @param key Key.
+     * @param oldVal Old value.
+     * @param val Current value.
+     */
+    void CheckNextEvent(const K& key, boost::optional<V> oldVal, boost::optional<V> val)
+    {
+        CacheEntryEvent<K, V> event;
+        bool success = eventQueue.Pull(event, boost::chrono::seconds(1));
+
+        BOOST_REQUIRE(success);
+
+        BOOST_CHECK_EQUAL(event.GetKey(), key);
+        BOOST_CHECK_EQUAL(event.HasOldValue(), oldVal.is_initialized());
+        BOOST_CHECK_EQUAL(event.HasValue(), val.is_initialized());
+
+        if (oldVal && event.HasOldValue())
+            BOOST_CHECK_EQUAL(event.GetOldValue().value, oldVal->value);
+
+        if (val && event.HasValue())
+            BOOST_CHECK_EQUAL(event.GetValue().value, val->value);
+    }
+
+    /*
+     * Check that there is no event for the specified ammount of time.
+     *
+     * @param timeout Timeout.
+     */
+    template <typename Rep, typename Period>
+    void CheckNoEvent(const boost::chrono::duration<Rep, Period>& timeout)
+    {
+        CacheEntryEvent<K, V> event;
+        bool success = eventQueue.Pull(event, timeout);
+
+        BOOST_REQUIRE(!success);
+    }
+
+private:
+    // Events queue.
+    ConcurrentQueue< CacheEntryEvent<K, V> > eventQueue;
+};
+
+/*
+ * Test entry.
+ */
+struct TestEntry
+{
+    /*
+     * Default constructor.
+     */
+    TestEntry() : value(0)
+    {
+        // No-op.
+    }
+
+    /*
+     * Constructor.
+     */
+    TestEntry(int32_t val) : value(val)
+    {
+        // No-op.
+    }
+
+    /* Value */
+    int32_t value;
+};
+
+namespace ignite
+{
+    namespace binary
+    {
+        /**
+        * Binary type definition.
+        */
+        IGNITE_BINARY_TYPE_START(TestEntry)
+            IGNITE_BINARY_GET_TYPE_ID_AS_HASH(TestEntry)
+            IGNITE_BINARY_GET_TYPE_NAME_AS_IS(TestEntry)
+            IGNITE_BINARY_GET_FIELD_ID_AS_HASH
+            IGNITE_BINARY_GET_HASH_CODE_ZERO(TestEntry)
+            IGNITE_BINARY_IS_NULL_FALSE(TestEntry)
+            IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(TestEntry)
+
+            void Write(BinaryWriter& writer, const TestEntry& obj)
+            {
+                writer.WriteInt32("value", obj.value);
+            }
+
+            TestEntry Read(BinaryReader& reader)
+            {
+                TestEntry res;
+                res.value = reader.ReadInt32("value");
+
+                return res;
+            }
+
+        IGNITE_BINARY_TYPE_END
+    }
+}
+
+/*
+ * Test setup fixture.
+ */
+struct ContinuousQueryTestSuiteFixture
+{
+    Ignite grid;
+
+    Cache<int, TestEntry> cache;
+
+    /*
+     * Get configuration for nodes.
+     */
+    IgniteConfiguration GetConfiguration()
+    {
+        IgniteConfiguration cfg;
+
+        cfg.jvmOpts.push_back("-Xdebug");
+        cfg.jvmOpts.push_back("-Xnoagent");
+        cfg.jvmOpts.push_back("-Djava.compiler=NONE");
+        cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005");
+        cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError");
+
+#ifdef IGNITE_TESTS_32
+        cfg.jvmInitMem = 256;
+        cfg.jvmMaxMem = 768;
+#else
+        cfg.jvmInitMem = 1024;
+        cfg.jvmMaxMem = 4096;
+#endif
+
+        char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH");
+
+        cfg.springCfgPath = std::string(cfgPath).append("/").append("cache-query-continuous.xml");
+
+        return cfg;
+    }
+
+    /*
+     * Constructor.
+     */
+    ContinuousQueryTestSuiteFixture() :
+        grid(Ignition::Start(GetConfiguration(), "node-01")),
+        cache(grid.GetCache<int, TestEntry>("transactional_no_backup"))
+    {
+        // No-op.
+    }
+
+    /*
+     * Destructor.
+     */
+    ~ContinuousQueryTestSuiteFixture()
+    {
+        Ignition::StopAll(false);
+
+        grid = Ignite();
+    }
+};
+
+void CheckEvents(Cache<int, TestEntry>& cache, Listener<int, TestEntry>& lsnr)
+{
+    cache.Put(1, TestEntry(10));
+    lsnr.CheckNextEvent(1, boost::none, TestEntry(10));
+
+    cache.Put(1, TestEntry(20));
+    lsnr.CheckNextEvent(1, TestEntry(10), TestEntry(20));
+
+    cache.Put(2, TestEntry(20));
+    lsnr.CheckNextEvent(2, boost::none, TestEntry(20));
+
+    cache.Remove(1);
+    lsnr.CheckNextEvent(1, TestEntry(20), boost::none);
+}
+
+BOOST_FIXTURE_TEST_SUITE(ContinuousQueryTestSuite, ContinuousQueryTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(TestBasic)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQueryScan)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, ScanQuery());
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 3);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 11);
+    BOOST_CHECK_EQUAL(vals[1].GetKey(), 22);
+    BOOST_CHECK_EQUAL(vals[2].GetKey(), 33);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 111);
+    BOOST_CHECK_EQUAL(vals[1].GetValue().value, 222);
+    BOOST_CHECK_EQUAL(vals[2].GetValue().value, 333);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQuerySql)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, SqlQuery("TestEntry", "value > 200"));
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 2);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 22);
+    BOOST_CHECK_EQUAL(vals[1].GetKey(), 33);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222);
+    BOOST_CHECK_EQUAL(vals[1].GetValue().value, 333);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQueryText)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, TextQuery("TestEntry", "222"));
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 1);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 22);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestBasicNoExcept)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    IgniteError err;
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, err);
+
+    BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQueryScanNoExcept)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    IgniteError err;
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, ScanQuery(), err);
+
+    BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS);
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 3);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 11);
+    BOOST_CHECK_EQUAL(vals[1].GetKey(), 22);
+    BOOST_CHECK_EQUAL(vals[2].GetKey(), 33);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 111);
+    BOOST_CHECK_EQUAL(vals[1].GetValue().value, 222);
+    BOOST_CHECK_EQUAL(vals[2].GetValue().value, 333);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQuerySqlNoExcept)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    IgniteError err;
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, SqlQuery("TestEntry", "value > 200"), err);
+
+    BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS);
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 2);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 22);
+    BOOST_CHECK_EQUAL(vals[1].GetKey(), 33);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222);
+    BOOST_CHECK_EQUAL(vals[1].GetValue().value, 333);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestInitialQueryTextNoExcept)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    cache.Put(11, TestEntry(111));
+    cache.Put(22, TestEntry(222));
+    cache.Put(33, TestEntry(333));
+
+    IgniteError err;
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, TextQuery("TestEntry", "222"), err);
+
+    BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS);
+
+    std::vector< CacheEntry<int, TestEntry> > vals;
+
+    handle.GetInitialQueryCursor().GetAll(vals);
+
+    BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError);
+
+    BOOST_REQUIRE_EQUAL(vals.size(), 1);
+
+    BOOST_CHECK_EQUAL(vals[0].GetKey(), 22);
+
+    BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestExpiredQuery)
+{
+    Listener<int, TestEntry> lsnr;
+    ContinuousQueryHandle<int, TestEntry> handle;
+
+    {
+        // Query scope.
+        ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+        handle = cache.QueryContinuous(qry);
+    }
+
+    // Query is destroyed here.
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestSetGetLocal)
+{
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    BOOST_CHECK(!qry.GetLocal());
+
+    qry.SetLocal(true);
+
+    BOOST_CHECK(qry.GetLocal());
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry);
+
+    BOOST_CHECK(qry.GetLocal());
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestGetSetBufferSize)
+{
+    typedef ContinuousQuery<int, TestEntry> QueryType;
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    BOOST_CHECK_EQUAL(qry.GetBufferSize(), QueryType::DEFAULT_BUFFER_SIZE);
+
+    qry.SetBufferSize(2 * QueryType::DEFAULT_BUFFER_SIZE);
+
+    BOOST_CHECK_EQUAL(qry.GetBufferSize(), 2 * QueryType::DEFAULT_BUFFER_SIZE);
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry);
+
+    BOOST_CHECK_EQUAL(qry.GetBufferSize(), 2 * QueryType::DEFAULT_BUFFER_SIZE);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestGetSetTimeInterval)
+{
+    typedef ContinuousQuery<int, TestEntry> QueryType;
+    Listener<int, TestEntry> lsnr;
+
+    ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr));
+
+    qry.SetBufferSize(10);
+
+    BOOST_CHECK_EQUAL(qry.GetTimeInterval(), static_cast<int>(QueryType::DEFAULT_TIME_INTERVAL));
+
+    qry.SetTimeInterval(500);
+
+    BOOST_CHECK_EQUAL(qry.GetTimeInterval(), 500);
+
+    ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry);
+
+    BOOST_CHECK_EQUAL(qry.GetTimeInterval(), 500);
+
+    CheckEvents(cache, lsnr);
+}
+
+BOOST_AUTO_TEST_CASE(TestPublicPrivateConstantsConsistence)
+{
+    typedef ContinuousQuery<int, TestEntry> QueryType;
+    typedef impl::cache::query::continuous::ContinuousQueryImpl<int, TestEntry> QueryImplType;
+    
+    BOOST_CHECK_EQUAL(static_cast<int>(QueryImplType::DEFAULT_TIME_INTERVAL),
+        static_cast<int>(QueryType::DEFAULT_TIME_INTERVAL));
+
+    BOOST_CHECK_EQUAL(static_cast<int>(QueryImplType::DEFAULT_BUFFER_SIZE),
+        static_cast<int>(QueryType::DEFAULT_BUFFER_SIZE));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/handle_registry_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/handle_registry_test.cpp b/modules/platforms/cpp/core-test/src/handle_registry_test.cpp
index bc4a654..0956d9b 100644
--- a/modules/platforms/cpp/core-test/src/handle_registry_test.cpp
+++ b/modules/platforms/cpp/core-test/src/handle_registry_test.cpp
@@ -36,7 +36,7 @@ struct HandleRegistryTestProbe
     }
 };
 
-class HandleRegistryTestEntry : public HandleRegistryEntry
+class HandleRegistryTestEntry
 {
 public:
     HandleRegistryTestEntry(HandleRegistryTestProbe* probe) : probe(probe)
@@ -67,9 +67,9 @@ BOOST_AUTO_TEST_CASE(TestCritical)
     HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1);
     HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2);
 
-    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry0));
-    int64_t hnd1 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry1));
-    int64_t hnd2 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry2));
+    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0));
+    int64_t hnd1 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry1));
+    int64_t hnd2 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry2));
 
     BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0);
     BOOST_REQUIRE(!probe0.deleted);
@@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(TestCritical)
     HandleRegistryTestProbe closedProbe;
     HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe);
 
-    int64_t closedHnd = closedReg.AllocateCritical(SharedPointer<HandleRegistryEntry>(closedEntry));
+    int64_t closedHnd = closedReg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(closedEntry));
     BOOST_REQUIRE(closedHnd == -1);
     BOOST_REQUIRE(closedProbe.deleted);
 }
@@ -126,9 +126,9 @@ BOOST_AUTO_TEST_CASE(TestNonCritical)
     HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1);
     HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2);
 
-    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry0));
-    int64_t hnd1 = reg.Allocate(SharedPointer<HandleRegistryEntry>(entry1));
-    int64_t hnd2 = reg.Allocate(SharedPointer<HandleRegistryEntry>(entry2));
+    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0));
+    int64_t hnd1 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry1));
+    int64_t hnd2 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry2));
 
     BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0);
     BOOST_REQUIRE(!probe0.deleted);
@@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(TestNonCritical)
     HandleRegistryTestProbe closedProbe;
     HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe);
 
-    int64_t closedHnd = closedReg.Allocate(SharedPointer<HandleRegistryEntry>(closedEntry));
+    int64_t closedHnd = closedReg.Allocate(SharedPointer<HandleRegistryTestEntry>(closedEntry));
     BOOST_REQUIRE(closedHnd == -1);
     BOOST_REQUIRE(closedProbe.deleted);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/reference_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/reference_test.cpp b/modules/platforms/cpp/core-test/src/reference_test.cpp
new file mode 100644
index 0000000..f5c3e8d
--- /dev/null
+++ b/modules/platforms/cpp/core-test/src/reference_test.cpp
@@ -0,0 +1,412 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.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.
+ */
+
+#ifndef _MSC_VER
+    #define BOOST_TEST_DYN_LINK
+#endif
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/smart_ptr.hpp>
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
+
+#include <ignite/reference.h>
+
+using namespace ignite;
+using namespace boost::unit_test;
+
+class LivenessMarker
+{
+public:
+    LivenessMarker(bool& flag) :
+        flag(flag)
+    {
+        flag = true;
+    }
+
+    LivenessMarker(const LivenessMarker& other) :
+        flag(other.flag)
+    {
+        // No-op.
+    }
+
+    LivenessMarker& operator=(const LivenessMarker& other)
+    {
+        flag = other.flag;
+
+        return *this;
+    }
+
+    ~LivenessMarker()
+    {
+        flag = false;
+    }
+
+private:
+    bool& flag;
+};
+
+class InstanceCounter
+{
+public:
+    InstanceCounter(int& counter) :
+        counter(&counter)
+    {
+        ++(*this->counter);
+    }
+
+    InstanceCounter(const InstanceCounter& other) :
+        counter(other.counter)
+    {
+        ++(*counter);
+    }
+
+    InstanceCounter& operator=(const InstanceCounter& other)
+    {
+        counter = other.counter;
+
+        ++(*counter);
+
+        return *this;
+    }
+
+    ~InstanceCounter()
+    {
+        --(*counter);
+    }
+
+private:
+    int* counter;
+};
+
+
+void TestFunction(Reference<LivenessMarker> ptr)
+{
+    Reference<LivenessMarker> copy(ptr);
+    Reference<LivenessMarker> copy2(ptr);
+}
+
+struct C1
+{
+    int c1;
+};
+
+struct C2
+{
+    int c2;
+};
+
+struct C3 : C1, C2
+{
+    int c3;
+};
+
+void TestFunction1(Reference<C1> c1, int expected)
+{
+    BOOST_CHECK_EQUAL(c1.Get().c1, expected);
+}
+
+void TestFunction2(Reference<C2> c2, int expected)
+{
+    BOOST_CHECK_EQUAL(c2.Get().c2, expected);
+}
+
+void TestFunction3(Reference<C3> c3, int expected)
+{
+    BOOST_CHECK_EQUAL(c3.Get().c3, expected);
+}
+
+void TestFunctionConst1(ConstReference<C1> c1, int expected)
+{
+    BOOST_CHECK_EQUAL(c1.Get().c1, expected);
+}
+
+void TestFunctionConst2(ConstReference<C2> c2, int expected)
+{
+    BOOST_CHECK_EQUAL(c2.Get().c2, expected);
+}
+
+void TestFunctionConst3(ConstReference<C3> c3, int expected)
+{
+    BOOST_CHECK_EQUAL(c3.Get().c3, expected);
+}
+
+BOOST_AUTO_TEST_SUITE(ReferenceTestSuite)
+
+BOOST_AUTO_TEST_CASE(StdSharedPointerTestBefore)
+{
+    bool objAlive = false;
+
+    std::shared_ptr<LivenessMarker> shared = std::make_shared<LivenessMarker>(objAlive);
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared);
+
+        BOOST_CHECK(objAlive);
+
+        shared.reset();
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(StdSharedPointerTestAfter)
+{
+    bool objAlive = false;
+
+    std::shared_ptr<LivenessMarker> shared = std::make_shared<LivenessMarker>(objAlive);
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared);
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(objAlive);
+
+    shared.reset();
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(StdAutoPointerTest)
+{
+    bool objAlive = false;
+
+    std::auto_ptr<LivenessMarker> autop(new LivenessMarker(objAlive));
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(autop);
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(StdUniquePointerTest)
+{
+    bool objAlive = false;
+
+    std::unique_ptr<LivenessMarker> unique(new LivenessMarker(objAlive));
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(std::move(unique));
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(BoostSharedPointerTestBefore)
+{
+    bool objAlive = false;
+
+    boost::shared_ptr<LivenessMarker> shared = boost::make_shared<LivenessMarker>(objAlive);
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared);
+
+        BOOST_CHECK(objAlive);
+
+        shared.reset();
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(BoostSharedPointerTestAfter)
+{
+    bool objAlive = false;
+
+    boost::shared_ptr<LivenessMarker> shared = boost::make_shared<LivenessMarker>(objAlive);
+
+    BOOST_CHECK(objAlive);
+
+    {
+        Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared);
+
+        BOOST_CHECK(objAlive);
+    }
+
+    BOOST_CHECK(objAlive);
+
+    shared.reset();
+
+    BOOST_CHECK(!objAlive);
+}
+
+BOOST_AUTO_TEST_CASE(PassingToFunction)
+{
+    bool objAlive = false;
+
+    std::shared_ptr<LivenessMarker> stdShared = std::make_shared<LivenessMarker>(objAlive);
+    std::unique_ptr<LivenessMarker> stdUnique(new LivenessMarker(objAlive));
+    std::auto_ptr<LivenessMarker> stdAuto(new LivenessMarker(objAlive));
+
+    boost::shared_ptr<LivenessMarker> boostShared = boost::make_shared<LivenessMarker>(objAlive);
+
+    TestFunction(MakeReferenceFromSmartPointer(stdShared));
+    TestFunction(MakeReferenceFromSmartPointer(std::move(stdUnique)));
+    TestFunction(MakeReferenceFromSmartPointer(stdAuto));
+
+    TestFunction(MakeReferenceFromSmartPointer(boostShared));
+}
+
+BOOST_AUTO_TEST_CASE(CopyTest)
+{
+    int instances = 0;
+
+    {
+        InstanceCounter counter(instances);
+
+        BOOST_CHECK_EQUAL(instances, 1);
+
+        {
+            Reference<InstanceCounter> copy = MakeReferenceFromCopy(counter);
+
+            BOOST_CHECK_EQUAL(instances, 2);
+        }
+
+        BOOST_CHECK_EQUAL(instances, 1);
+    }
+
+    BOOST_CHECK_EQUAL(instances, 0);
+}
+
+BOOST_AUTO_TEST_CASE(OwningPointerTest)
+{
+    int instances = 0;
+
+    {
+        InstanceCounter *counter = new InstanceCounter(instances);
+
+        BOOST_CHECK_EQUAL(instances, 1);
+
+        {
+            Reference<InstanceCounter> owned = MakeReferenceFromOwningPointer(counter);
+
+            BOOST_CHECK_EQUAL(instances, 1);
+        }
+
+        BOOST_CHECK_EQUAL(instances, 0);
+    }
+
+    BOOST_CHECK_EQUAL(instances, 0);
+}
+
+BOOST_AUTO_TEST_CASE(NonOwningPointerTest1)
+{
+    int instances = 0;
+
+    {
+        InstanceCounter counter(instances);
+
+        BOOST_CHECK_EQUAL(instances, 1);
+
+        {
+            Reference<InstanceCounter> copy = MakeReference(counter);
+
+            BOOST_CHECK_EQUAL(instances, 1);
+        }
+
+        BOOST_CHECK_EQUAL(instances, 1);
+    }
+
+    BOOST_CHECK_EQUAL(instances, 0);
+}
+
+BOOST_AUTO_TEST_CASE(NonOwningPointerTest2)
+{
+    int instances = 0;
+
+    InstanceCounter* counter = new InstanceCounter(instances);
+
+    BOOST_CHECK_EQUAL(instances, 1);
+
+    {
+        Reference<InstanceCounter> copy = MakeReference(*counter);
+
+        BOOST_CHECK_EQUAL(instances, 1);
+
+        delete counter;
+
+        BOOST_CHECK_EQUAL(instances, 0);
+    }
+
+    BOOST_CHECK_EQUAL(instances, 0);
+}
+
+BOOST_AUTO_TEST_CASE(CastTest)
+{
+    C3 testVal;
+
+    testVal.c1 = 1;
+    testVal.c2 = 2;
+    testVal.c3 = 3;
+
+    TestFunction1(MakeReference(testVal), 1);
+    TestFunction2(MakeReference(testVal), 2);
+    TestFunction3(MakeReference(testVal), 3);
+
+    TestFunction1(MakeReferenceFromCopy(testVal), 1);
+    TestFunction2(MakeReferenceFromCopy(testVal), 2);
+    TestFunction3(MakeReferenceFromCopy(testVal), 3);
+}
+
+BOOST_AUTO_TEST_CASE(ConstTest)
+{
+    C3 testVal;
+
+    testVal.c1 = 1;
+    testVal.c2 = 2;
+    testVal.c3 = 3;
+
+    TestFunctionConst1(MakeConstReference(testVal), 1);
+    TestFunctionConst2(MakeConstReference(testVal), 2);
+    TestFunctionConst3(MakeConstReference(testVal), 3);
+
+    TestFunctionConst1(MakeConstReferenceFromCopy(testVal), 1);
+    TestFunctionConst2(MakeConstReferenceFromCopy(testVal), 2);
+    TestFunctionConst3(MakeConstReferenceFromCopy(testVal), 3);
+
+    TestFunctionConst1(MakeReference(testVal), 1);
+    TestFunctionConst2(MakeReference(testVal), 2);
+    TestFunctionConst3(MakeReference(testVal), 3);
+
+    TestFunctionConst1(MakeReferenceFromCopy(testVal), 1);
+    TestFunctionConst2(MakeReferenceFromCopy(testVal), 2);
+    TestFunctionConst3(MakeReferenceFromCopy(testVal), 3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/Makefile.am b/modules/platforms/cpp/core/Makefile.am
index 97523cf..758e68d 100644
--- a/modules/platforms/cpp/core/Makefile.am
+++ b/modules/platforms/cpp/core/Makefile.am
@@ -59,6 +59,7 @@ libignite_la_SOURCES = \
     src/impl/ignite_environment.cpp \
     src/impl/binary/binary_type_updater_impl.cpp \
     src/impl/handle_registry.cpp \
+    src/impl/cache/query/continuous/continuous_query_handle_impl.cpp \
     src/impl/cache/query/query_impl.cpp \
     src/impl/cache/cache_impl.cpp \
     src/impl/cache/query/query_batch.cpp \


Mime
View raw message