blob: eb6410c39c8720be95e85f1bc12ff791c0851ea7 [file] [log] [blame]
/*
* 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.
*/
#pragma once
#include "geode_defs.hpp"
#include "begin_native.hpp"
#include <geode/CacheableBuiltins.hpp>
#include "end_native.hpp"
#include "Serializable.hpp"
#include "ExceptionTypes.hpp"
#include "impl/PdxInstanceImpl.hpp"
#include "native_shared_ptr.hpp"
#include "native_unique_ptr.hpp"
using namespace System;
using namespace System::Collections::Generic;
#pragma managed
namespace Apache
{
namespace Geode
{
namespace Client
{
namespace Internal
{
/// <summary>
/// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as
/// a distributable object for caching.
/// </summary>
template <int8_t TYPEID, typename HSTYPE>
public ref class CacheableHashSetType
: public IDataSerializablePrimitive,
public Serializable,
public ICollection<Object^>
{
public:
virtual void ToData(DataOutput^ output)
{
output->WriteArrayLen(this->Count);
auto set = dynamic_cast<HSTYPE*>(m_nativeptr->get());
for (const auto& iter : *set) {
auto key = TypeRegistry::GetManagedValueGeneric<Object^>(iter);
output->WriteObject(key);
}
GC::KeepAlive(this);
}
virtual void FromData(DataInput^ input)
{
int len = input->ReadArrayLen();
if (len > 0)
{
for (int i = 0; i < len; i++)
{
Object^ key = (input->ReadObject());
this->Add(key);
}
}
}
property System::UInt64 ObjectSize
{
System::UInt64 get() override
{
System::UInt64 size = 0;
for each (Object^ key in this) {
if (key != nullptr)
//size += key->ObjectSize;
//TODO:: how should we do this now
size += 1;
}
return size;
}
}
int GetHashCode() override
{
IEnumerator<Object^>^ ie = GetEnumerator();
int h = 0;
while (ie->MoveNext() == true)
{
h = h + PdxInstanceImpl::deepArrayHashCode(ie->Current);
}
return h;
}
bool Equals(Object^ other) override
{
if (other == nullptr)
return false;
CacheableHashSetType^ otherCHST = dynamic_cast<CacheableHashSetType^>(other);
if (otherCHST == nullptr)
return false;
if (Count != otherCHST->Count)
return false;
IEnumerator<Object^>^ ie = GetEnumerator();
while (ie->MoveNext() == true)
{
if (otherCHST->Contains(ie->Current))
return true;
else
return false;
}
return true;
}
/// <summary>
/// Enumerator for <c>CacheableHashSet</c> class.
/// </summary>
ref class Enumerator sealed
: public IEnumerator<Object^>
{
public:
// Region: IEnumerator<ICacheableKey^> Members
/// <summary>
/// Gets the element in the collection at the current
/// position of the enumerator.
/// </summary>
/// <returns>
/// The element in the collection at the current position
/// of the enumerator.
/// </returns>
property Object^ Current
{
virtual Object^ get() =
IEnumerator<Object^>::Current::get
{
if (!m_started) {
throw gcnew System::InvalidOperationException(
"Call MoveNext first.");
}
auto ret = TypeRegistry::GetManagedValueGeneric<Object^>(*(*(m_nativeptr->get())));
GC::KeepAlive(this);
return ret;
}
}
// End Region: IEnumerator<ICacheableKey^> Members
// Region: IEnumerator Members
/// <summary>
/// Advances the enumerator to the next element of the collection.
/// </summary>
/// <returns>
/// true if the enumerator was successfully advanced to the next
/// element; false if the enumerator has passed the end of
/// the collection.
/// </returns>
virtual bool MoveNext()
{
auto nptr = m_nativeptr->get();
bool isEnd = dynamic_cast<HSTYPE*>(m_set->m_nativeptr->get())->end() == *nptr;
if (!m_started) {
m_started = true;
}
else {
if (!isEnd) {
(*nptr)++;
isEnd = dynamic_cast<HSTYPE*>(m_set->m_nativeptr->get())->end() == *nptr;
}
}
GC::KeepAlive(this);
return !isEnd;
}
/// <summary>
/// Sets the enumerator to its initial position, which is before
/// the first element in the collection.
/// </summary>
virtual void Reset()
{
try
{
m_nativeptr = gcnew native_unique_ptr<typename HSTYPE::iterator>(
std::make_unique<typename HSTYPE::iterator>(
dynamic_cast<HSTYPE*>(m_set->m_nativeptr->get())->begin()));
}
finally
{
GC::KeepAlive(m_nativeptr);
}
m_started = false;
}
!Enumerator() {}
~Enumerator() {}
// End Region: IEnumerator Members
internal:
/// <summary>
/// Internal constructor to wrap a native object pointer
/// </summary>
/// <param name="nativeptr">The native object pointer</param>
inline Enumerator(CacheableHashSetType<TYPEID, HSTYPE>^ set)
: m_set(set) {
Reset();
}
private:
// Region: IEnumerator Members
/// <summary>
/// Gets the current element in the collection.
/// </summary>
/// <returns>
/// The current element in the collection.
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// The enumerator is positioned before the first element of
/// the collection or after the last element.
/// </exception>
property Object^ ICurrent
{
virtual Object^ get() sealed =
System::Collections::IEnumerator::Current::get
{
return Current;
}
}
// End Region: IEnumerator Members
bool m_started;
CacheableHashSetType<TYPEID, HSTYPE>^ m_set;
native_unique_ptr<typename HSTYPE::iterator>^ m_nativeptr;
};
property int8_t DsCode
{
virtual int8_t get()
{
return TYPEID;
}
}
/// <summary>
/// Get the largest possible size of the <c>CacheableHashSet</c>.
/// </summary>
property System::Int32 MaxSize
{
inline System::Int32 get()
{
try
{
return static_cast<int>(dynamic_cast<HSTYPE*>(m_nativeptr->get())->max_size());
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
}
/// <summary>
/// True if the <c>CacheableHashSet</c>'s size is 0.
/// </summary>
property bool IsEmpty
{
inline bool get()
{
try
{
return dynamic_cast<HSTYPE*>(m_nativeptr->get())->empty();
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
}
/// <summary>
/// Get the number of buckets used by the HashSet.
/// </summary>
property System::Int32 BucketCount
{
inline System::Int32 get()
{
try
{
return static_cast<int>(dynamic_cast<HSTYPE*>(m_nativeptr->get())->bucket_count());
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
}
/// <summary>
/// Increases the bucket count to at least <c>size</c> elements.
/// </summary>
/// <param name="size">The new size of the HashSet.</param>
virtual void Resize(System::Int32 size) sealed
{
try
{
dynamic_cast<HSTYPE*>(m_nativeptr->get())->reserve(size);
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
/// <summary>
/// Swap the contents of this <c>CacheableHashSet</c>
/// with the given one.
/// </summary>
/// <param name="other">
/// The other CacheableHashSet to use for swapping.
/// </param>
virtual void Swap(CacheableHashSetType<TYPEID, HSTYPE>^ other) sealed
{
try
{
if (other != nullptr) {
dynamic_cast<HSTYPE*>(m_nativeptr->get())->swap(
*dynamic_cast<HSTYPE*>(other->m_nativeptr->get()));
}
}
finally
{
GC::KeepAlive(m_nativeptr);
GC::KeepAlive(other->m_nativeptr);
}
}
// Region: ICollection<ICacheableKey^> Members
/// <summary>
/// Adds an item to the <c>CacheableHashSet</c>.
/// </summary>
/// <param name="item">
/// The object to add to the collection.
/// </param>
virtual void Add(Object^ item)
{
_GF_MG_EXCEPTION_TRY2/* due to auto replace */
try
{
dynamic_cast<HSTYPE*>(m_nativeptr->get())->insert(Serializable::GetUnmanagedValueGeneric(item));
}
finally
{
GC::KeepAlive(m_nativeptr);
}
_GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */
}
/// <summary>
/// Removes all items from the <c>CacheableHashSet</c>.
/// </summary>
virtual void Clear()
{
try
{
dynamic_cast<HSTYPE*>(m_nativeptr->get())->clear();
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
/// <summary>
/// Determines whether the <c>CacheableHashSet</c> contains
/// a specific value.
/// </summary>
/// <param name="item">
/// The object to locate in the <c>CacheableHashSet</c>.
/// </param>
/// <returns>
/// true if item is found in the <c>CacheableHashSet</c>;
/// otherwise false.
/// </returns>
virtual bool Contains(Object^ item)
{
try
{
return dynamic_cast<HSTYPE*>(m_nativeptr->get())->find(Serializable::GetUnmanagedValueGeneric(item)) != dynamic_cast<HSTYPE*>(m_nativeptr->get())->end();
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
/// <summary>
/// Copies the elements of the <c>CacheableHashSet</c> to an
/// <c>System.Array</c>, starting at a particular
/// <c>System.Array</c> index.
/// </summary>
/// <param name="array">
/// The one-dimensional System.Array that is the destination of the
/// elements copied from <c>CacheableHashSet</c>. The
/// <c>System.Array</c> must have zero-based indexing.
/// </param>
/// <param name="arrayIndex">
/// The zero-based index in array at which copying begins.
/// </param>
/// <exception cref="IllegalArgumentException">
/// arrayIndex is less than 0 or array is null.
/// </exception>
/// <exception cref="OutOfRangeException">
/// arrayIndex is equal to or greater than the length of array.
/// -or-The number of elements in the source <c>CacheableHashSet</c>
/// is greater than the available space from arrayIndex to the end
/// of the destination array.
/// </exception>
virtual void CopyTo(array<Object^>^ array, System::Int32 arrayIndex)
{
if (array == nullptr || arrayIndex < 0) {
throw gcnew IllegalArgumentException("CacheableHashSet.CopyTo():"
" array is null or array index is less than zero");
}
auto set = dynamic_cast<HSTYPE*>(m_nativeptr->get());
System::Int32 index = arrayIndex;
if (arrayIndex >= array->Length ||
array->Length < (arrayIndex + (System::Int32)set->size())) {
throw gcnew OutOfRangeException("CacheableHashSet.CopyTo():"
" array index is beyond the HashSet or length of given "
"array is less than that required to copy all the "
"elements from HashSet");
}
for (const auto& iter : *set) {
array[index++] = TypeRegistry::GetManagedValueGeneric<Object^>(iter);
}
GC::KeepAlive(m_nativeptr);
}
/// <summary>
/// Gets the number of elements contained in the
/// <c>CacheableHashSet</c>.
/// </summary>
virtual property System::Int32 Count
{
virtual System::Int32 get()
{
try
{
return static_cast<int>(dynamic_cast<HSTYPE*>(m_nativeptr->get())->size());
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
}
/// <summary>
/// Removes the first occurrence of a specific object from the
/// <c>CacheableHashSet</c>.
/// </summary>
/// <param name="item">
/// The object to remove from the <c>CacheableHashSet</c>.
/// </param>
/// <returns>
/// true if item was successfully removed from the
/// <c>CacheableHashSet</c>; otherwise, false. This method also
/// returns false if item is not found in the original
/// <c>CacheableHashSet</c>.
/// </returns>
virtual bool Remove(Object^ item)
{
try
{
return (dynamic_cast<HSTYPE*>(m_nativeptr->get())->erase(Serializable::GetUnmanagedValueGeneric(item)) > 0);
}
finally
{
GC::KeepAlive(m_nativeptr);
}
}
/// <summary>
/// Gets a value indicating whether the collection is read-only.
/// </summary>
/// <returns>
/// always false for <c>CacheableHashSet</c>
/// </returns>
virtual property bool IsReadOnly
{
virtual bool get()
{
return false;
}
}
// End Region: ICollection<ICacheableKey^> Members
// Region: IEnumerable<ICacheableKey^> Members
/// <summary>
/// Returns an enumerator that iterates through the
/// <c>CacheableHashSet</c>.
/// </summary>
/// <returns>
/// A <c>System.Collections.Generic.IEnumerator</c> that
/// can be used to iterate through the <c>CacheableHashSet</c>.
/// </returns>
virtual IEnumerator<Object^>^ GetEnumerator()
{
return gcnew Enumerator(this);
}
// End Region: IEnumerable<ICacheableKey^> Members
internal:
/// <summary>
/// Factory function to register wrapper
/// </summary>
static ISerializable^ Create(apache::geode::client::Serializable* obj)
{
return (obj != NULL ?
gcnew CacheableHashSetType<TYPEID, HSTYPE>(obj) : nullptr);
}
private:
// Region: IEnumerable Members
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <c>System.Collections.IEnumerator</c> object that can be used
/// to iterate through the collection.
/// </returns>
virtual System::Collections::IEnumerator^ GetIEnumerator() sealed =
System::Collections::IEnumerable::GetEnumerator
{
return GetEnumerator();
}
// End Region: IEnumerable Members
protected:
/// <summary>
/// Private constructor to wrap a native object pointer
/// </summary>
/// <param name="nativeptr">The native object pointer</param>
inline CacheableHashSetType<TYPEID, HSTYPE>(std::shared_ptr<apache::geode::client::Serializable> nativeptr)
: Serializable(nativeptr) { }
/// <summary>
/// Allocates a new empty instance.
/// </summary>
inline CacheableHashSetType<TYPEID, HSTYPE>()
: Serializable(HSTYPE::createDeserializable())
{ }
/// <summary>
/// Allocates a new empty instance with given initial size.
/// </summary>
/// <param name="size">The initial size of the HashSet.</param>
inline CacheableHashSetType<TYPEID, HSTYPE>(System::Int32 size)
: Serializable(HSTYPE::create(size))
{ }
};
}
#define _GFCLI_CACHEABLEHASHSET_DEF_GENERIC(m, HSTYPE) \
public ref class m : public Internal::CacheableHashSetType<static_cast<int8_t>(native::internal::DSCode::m), HSTYPE> \
{ \
public: \
/** <summary>
* Allocates a new empty instance.
* </summary>
*/ \
inline m() \
: Internal::CacheableHashSetType<static_cast<int8_t>(native::internal::DSCode::m), HSTYPE>() {} \
\
/** <summary>
* Allocates a new instance with the given size.
* </summary>
* <param name="size">the initial size of the new instance</param>
*/ \
inline m(System::Int32 size) \
: Internal::CacheableHashSetType<static_cast<int8_t>(native::internal::DSCode::m), HSTYPE>(size) {} \
\
/** <summary>
* Static function to create a new empty instance.
* </summary>
*/ \
inline static m^ Create() \
{ \
return gcnew m(); \
} \
\
/** <summary>
* Static function to create a new instance with the given size.
* </summary>
*/ \
inline static m^ Create(System::Int32 size) \
{ \
return gcnew m(size); \
} \
\
/* <summary>
* Factory function to register this class.
* </summary>
*/ \
static ISerializable^ CreateDeserializable() \
{ \
return gcnew m(); \
} \
\
internal: \
static ISerializable^ Create(std::shared_ptr<apache::geode::client::Serializable> obj) \
{ \
return gcnew m(obj); \
} \
\
private: \
inline m(std::shared_ptr<apache::geode::client::Serializable> nativeptr) \
: Internal::CacheableHashSetType<static_cast<int8_t>(native::internal::DSCode::m), HSTYPE>(nativeptr) { } \
};
/// <summary>
/// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as
/// a distributable object for caching.
/// </summary>
_GFCLI_CACHEABLEHASHSET_DEF_GENERIC(CacheableHashSet,
apache::geode::client::CacheableHashSet);
/// <summary>
/// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as
/// a distributable object for caching. This is provided for compability
/// with java side though is functionally identical to
/// <c>CacheableHashSet</c> i.e. does not provide the linked semantics of
/// java <c>LinkedHashSet</c>.
/// </summary>
_GFCLI_CACHEABLEHASHSET_DEF_GENERIC(CacheableLinkedHashSet,
apache::geode::client::CacheableLinkedHashSet);
} // namespace Client
} // namespace Geode
} // namespace Apache