[Programming C++] From shared_ptr to shared_ptr maintaining the use_count

Sometimes we need to store shared data pointers in an anoymous shared pointer shared_ptr<void>. The problem is when you want to convert back the shared_ptr<void> to shared_ptr<T> again. A priori, it is not possible, but we can do some tricks to solve this issue. Neddless to say that the first solution is – of course –  NOT USE shared_ptr<void>. Try to use boost::any or boost::variant objects in your problem. But still, if there may be some strange cases where it can be interesting the use of  anonymous shared_ptrs

The most you can until the momment is getting the original data is using the shared_ptr<void>::get() method to get the void* pointer. However you must maintain the shared_ptr<void> alive if you want to avoid the segmentation fault. The following test would FAIL in the last line:

TEST(basic_test, original_from_shared_void_to_t)
{
std::shared_ptr<A> a(new A);
std::shared_ptr<void> b =a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);

 

a=std::shared_ptr<A>();
ASSERT_TRUE(a.use_count()==0);
ASSERT_TRUE(b.use_count()==1);

 

printf(“Testing access memory…\n”);
A* data=(A*)b.get();
data->foo(); //you can access to the fields and methods
//OK by the moment..

b=std::shared_ptr<void>();
ASSERT_TRUE(b.use_count()==0);

 

//and now crash because memory has been freed…

data->foo(); //segmentation fault
}

Do you have any idea? Perhaps you are thinking in this one (but it does not work):

std::shared_ptr<A> data= std::shared_ptr<A>((A*)b.get());
data->foo(); //it works because b still references it

//but the problem is the next fact
ASSERT_TRUE(b.use_count()==1);
ASSERT_TRUE(data.use_count()==1);
//both have different counts, they both should be 2 instead 1
//so here comes the crash…

b=std::shared_ptr<void>();
//the destructor is called
data->foo();

lesson lernt: you have to maintain b (or a copy of it) alive while the new pointer “data” is alive.

How to do it without think about it continuing working as always? The  solution is the “__magic_reinterpret_pointer_cast”. see the code:

template<typename T>
std::shared_ptr<T> __magic_reinterpret_pointer_cast(std::shared_ptr<void> b)
{
return std::shared_ptr<T>((T*)b.get(),[b](T* x){});
}

Whit it you can go back to your type shared_ptr<A> from shared_ptr<void> avoiding any segmentation fault. The trick is store a reference of the shared_ptr<void> inside the new shared_ptr<A>. Observe that there will be different “use counts” groups, so the use_count method is not reliable anymore. Appart from this everything look work well: See this example and please make me know other limitations on the approach if you notice it.

NOTE: Be careful because it has the same limitations to the reinterpet_cast. ¡¡This is not valid to cast to base or derived types!!. TEST(basic_test,t1)

TEST(basic_test, original_from_shared_void_to_t_reintrepret_cast)

{
std::shared_ptr<A> a(new A);
std::shared_ptr<void> b=a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);

//removing one instance
b=std::shared_ptr<void>();
ASSERT_TRUE(a.use_count()==1);
ASSERT_TRUE(b.use_count()==0);

//restoring it again
b=a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);
{
//”make magic trick
std::shared_ptr<A> c=__magic_reinterpret_pointer_cast<A>(b);

ASSERT_TRUE(a.use_count()==3);
ASSERT_TRUE(b.use_count()==3);
ASSERT_TRUE(c.use_count()==1); // THIS IS THE WARNING POINT

c=std::shared_ptr<A>();
ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);
}

{
//”make magic trick
std::shared_ptr<A> c=__magic_reinterpret_pointer_cast<A>(b);

ASSERT_TRUE(a.use_count()==3);
ASSERT_TRUE(b.use_count()==3);
ASSERT_TRUE(c.use_count()==1); // THIS IS THE WARNING POINT

a=std::shared_ptr<A>();
b=std::shared_ptr<void>();

ASSERT_TRUE(a.use_count()==0);
ASSERT_TRUE(b.use_count()==0);
ASSERT_TRUE(c.use_count()==1); // VOILA, STILL 1!
}
}

 

[Programming c#] Use structs instead classes in a loops

Structs in c# enable the development of efficient pieces of code where the managed dynamic memory is not required. Structs in .net are value types. That means that they can be allocated in the stack efficiently instead of the heap. Thanks to this you can have a chunk of data that acts like an object (it has fields and methods) but avoiding the call of the memory management system (garabage collection, that may even call to the operative system to reserve more memory).

For instance, let the simple struct A:

		struct A
		{
			public int val;

			public A(int v)
			{
				this.v=val;
			}

			public void foo()
			{
				Console.WriteLn(val);
			}
		}

The following sample shows the function “bar” that uses the struct “A” intensively in a loop (a typical scenario where efficiency may be very relevant).


         void bar()
         {
             for(int i=0;i<1000;i++)
             {
                 A a;
                 a.val=i;
                 a.foo();
             }
         }

The use of A as an struct instead a class has three main benefits:

  1.  First a construction function call is avoided. Avoiding function calls in loops may boost the process. For instance, function calls typically decreases the performance of the processor dynamic scheduling or even because of static optimization techniques like performed by the compiler or JITTER (such as loop unrolling).
  2. It is not required to call the dynamic memory management system. That means that the memory management system in .net does not need to create a new node for the object. Moreover any call to the operative system to reserve more memory for the process is totally avoided.
  3.  No garbage collection is required at all since the struct is not in the memory heap. The “deallocation of the object” is automatically done (with no processing cost) when the current function returns back to the calling function (change of stack frame).

However, sometimes it is required to make some kind of initialization process for the struct. Because of this c# structs can be initialization using a parametric constructor. Structs constructors are invoked using the “new” keyword. That may be confusing because the “new” keyword has been historically used in other languages (such as c++) as a method to reserve dynamic memory. If the constructor is called, the benefit 1 is lost, however the benefits 2 and 3 are still maintained.


         void bar()
         {
             for(int i=0;i<1000;i++)
             {
                 A a = new A(4);
                 a.foo();
             }
         }