Skip to content

Commit

Permalink
xholder_shared implementation (#149)
Browse files Browse the repository at this point in the history
xholder_shared implementation
  • Loading branch information
JohanMabille authored and SylvainCorlay committed Jul 9, 2018
1 parent 6c7db5f commit fdc9a74
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
83 changes: 83 additions & 0 deletions include/xwidgets/xholder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef XWIDGETS_HOLDER_HPP
#define XWIDGETS_HOLDER_HPP

#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <utility>
Expand Down Expand Up @@ -90,6 +91,12 @@ namespace xw
template <template <class> class CRTP>
xholder<CRTP> make_id_holder(xeus::xguid id);

template <template <class> class CRTP, class D, class... Args>
xholder<CRTP> make_shared_holder(Args&&... args);

template <template <class> class CRTP, class D>
xholder<CRTP> make_shared_holder(CRTP<D>* ptr);

/*************************************
* to_json and from_json declaration *
*************************************/
Expand Down Expand Up @@ -487,6 +494,10 @@ namespace xw
return it->second;
}

/*****************************
* xholder_id implementation *
*****************************/

namespace detail
{
template <template <class> class CRTP>
Expand Down Expand Up @@ -547,6 +558,78 @@ namespace xw
return xholder<CRTP>(new detail::xholder_id<CRTP>(id));
}

/*********************************
* xholder_shared implementation *
*********************************/

namespace detail
{
template <template <class> class CRTP, class D>
class xholder_shared : public xholder_impl<CRTP>
{
public:

using base_type = xholder_impl<CRTP>;
using pointer = std::shared_ptr<D>;

xholder_shared(pointer ptr)
: base_type(),
p_value(ptr)
{
}

xholder_shared(CRTP<D>* ptr)
: base_type(),
p_value(&(ptr->derived_cast()))
{
}

virtual ~xholder_shared() = default;
virtual base_type* clone() const override
{
return new xholder_shared(*this);
}

virtual void display() const override
{
p_value->display();
}

virtual xeus::xguid id() const override
{
return p_value->id();
}

virtual xtl::any value() & override
{
return xtl::closure(*p_value);
}

virtual const xtl::any value() const & override
{
return xtl::closure(*p_value);
}

private:

pointer p_value;
};
}

template <template <class> class CRTP, class D, class... Args>
inline xholder<CRTP> make_shared_holder(Args&&... args)
{
using impl_type = detail::xholder_shared<CRTP, D>;
return xholder<CRTP>(new impl_type(std::make_shared<D>(std::forward<Args>(args)...)));
}

template <template <class> class CRTP, class D>
inline xholder<CRTP> make_shared_holder(CRTP<D>* ptr)
{
using impl_type = detail::xholder_shared<CRTP, D>;
return xholder<CRTP>(new impl_type(ptr));
}

/**********************************************************
* Specialization of mime_bundle_repr for Jupyter Widgets *
**********************************************************/
Expand Down
68 changes: 68 additions & 0 deletions test/test_xholder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,72 @@ namespace xw
std::string res = hm["x"].template get<button>().description();
ASSERT_EQ(desc, res);
}

class button_tester : public xwidget<button_tester>
{
public:

button_tester(int value = 0)
: m_value(value)
{
++m_instance_count;
}

~button_tester()
{
--m_instance_count;
}

button_tester(const button_tester& rhs)
: m_value(rhs.m_value)
{
++m_instance_count;
}

button_tester(button_tester&& rhs)
: m_value(rhs.m_value)
{
++m_instance_count;
}

button_tester& operator=(const button_tester&) = default;
button_tester& operator=(button_tester&&) = default;

int value() const { return m_value; }

static int instance_count() { return m_instance_count; }

private:

int m_value;
static int m_instance_count;
};

int button_tester::m_instance_count = 0;

TEST(xholder, shared)
{
using map_type = std::map<std::string, xholder<xwidget>>;
map_type hm1, hm2;
button_tester* b = new button_tester;
hm1["x"] = make_shared_holder<xwidget>(b);
hm2["x"] = hm1["x"];
ASSERT_EQ(hm1["x"].id(), hm2["x"].id());
ASSERT_EQ(button_tester::instance_count(), 1);

hm1["y"] = make_shared_holder<xwidget, button_tester>(4);;
hm2["y"] = hm1["y"];
ASSERT_EQ(hm1["y"].template get<button_tester>().value(), hm2["y"].template get<button_tester>().value());
ASSERT_EQ(button_tester::instance_count(), 2);

hm1.erase("x");
ASSERT_EQ(button_tester::instance_count(), 2);
hm2.erase("x");
ASSERT_EQ(button_tester::instance_count(), 1);

hm1.erase("y");
ASSERT_EQ(button_tester::instance_count(), 1);
hm2.erase("y");
ASSERT_EQ(button_tester::instance_count(), 0);
}
}

0 comments on commit fdc9a74

Please sign in to comment.