#include <cstdio>
#include <iostream>
#include <cstring>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <vector>
#include <exception>
class Harry {
public:
Harry(const char* = NULL);
~Harry();
void hello();
private:
char *name;
};
class Betty : public Harry {
public:
Betty();
~Betty();
};
Harry::Harry(const char *name_) {
name = name_ ? strdup(name_) : NULL;
printf("-- Constructing Harry (%s)\n", name);
}
Harry::~Harry() {
printf("-- Deconstructing Harry (%s)\n", name);
free(name);
}
void Harry::hello() {
printf("-- Harry \"%s\" says hello\n", name);
}
Betty::Betty() {
printf("---- Constructing Betty\n");
}
Betty::~Betty() {
printf("---- Deconstructing Betty\n");
}
class RingNode {
public:
RingNode(const char*, const boost::shared_ptr<RingNode>&);
~RingNode();
void connect(const boost::shared_ptr<RingNode>&);
const char* get_name();
const boost::shared_ptr<RingNode>& get_node();
private:
boost::shared_ptr<RingNode> node;
char* name;
};
RingNode::RingNode(const char* name_, const boost::shared_ptr<RingNode>& node_) : node(node_) {
name = name_ ? strdup(name_) : NULL;
printf("++ Constructing RingNode (%s)\n", name);
}
RingNode::~RingNode() {
printf("++ Deconstructing RingNode (%s)\n", name);
free(name);
}
void RingNode::connect(const boost::shared_ptr<RingNode>& node_) {
node = node_;
}
const char* RingNode::get_name() {
return name;
}
const boost::shared_ptr<RingNode>& RingNode::get_node() {
return node;
}
class WeakRingNode {
public:
WeakRingNode(const char*, const boost::shared_ptr<WeakRingNode>&);
~WeakRingNode();
void connect(const boost::shared_ptr<WeakRingNode>&);
const char* get_name();
const boost::shared_ptr<WeakRingNode> get_node();
private:
boost::weak_ptr<WeakRingNode> node;
char* name;
};
WeakRingNode::WeakRingNode(const char* name_, const boost::shared_ptr<WeakRingNode>& node_) : node(node_) {
name = name_ ? strdup(name_) : NULL;
printf("++ Constructing RingNode (%s)\n", name);
}
WeakRingNode::~WeakRingNode() {
printf("++ Deconstructing RingNode (%s)\n", name);
free(name);
}
void WeakRingNode::connect(const boost::shared_ptr<WeakRingNode>& node_) {
node = node_;
}
const char* WeakRingNode::get_name() {
return name;
}
const boost::shared_ptr<WeakRingNode> WeakRingNode::get_node() {
return node.lock();
}
class Intruded {
public:
Intruded();
~Intruded();
private:
int counter;
friend void intrusive_ptr_add_ref(Intruded *const);
friend void intrusive_ptr_release(Intruded *const);
};
void intrusive_ptr_add_ref(Intruded *const);
void intrusive_ptr_release(Intruded *const);
Intruded::Intruded() : counter(0) {
printf("%% Creating Intruded\n");
}
Intruded::~Intruded() {
printf("%% Destroying Intruded\n");
}
void intrusive_ptr_add_ref(Intruded *const p) {
printf("%% Added. Now: %d\n", ++(p->counter));
}
void intrusive_ptr_release(Intruded *const p) {
printf("%% Removed. Now: %d\n", --(p->counter));
if(!p->counter) {
printf("%% Deleting Intruded because of count == 0...\n");
delete p;
}
}
class WithSharing : public boost::enable_shared_from_this<WithSharing> {
public:
boost::shared_ptr<WithSharing> get_shared() {
return shared_from_this();
}
};
using namespace std;
typedef vector< boost::shared_ptr<Harry> > SharedHarryVector;
void header(const char* label) {
char* bar = strdup(label);
cout << endl << label << endl;
memset(bar, '=', strlen(bar));
cout << bar << endl;
free(bar);
}
void play_dirty_harry() {
header("Dirty Harry - czego ze wskaznikami robic nie wolno");
Harry* tmp_harry;
boost::scoped_ptr<Harry> harry(tmp_harry = new Harry("Simple Class Harry"));
}
void play_nice_harry() {
header("play_nice_harry - scoped_ptr jak zmienna automatyczna");
boost::scoped_ptr<Harry> harry3(new Harry("Harry3"));
harry3->hello();
Harry harry4("Harry4");
harry4.hello();
}
void play_nice_harry3() {
header("play_nice_harry3 - operator \"new\" bez potrzeby wywolania delete");
boost::scoped_ptr<Harry> harry7;
bool needHarry = true;
if(needHarry)
harry7.reset(new Harry("Harry7"));
if(harry7) {
printf("-- Stwierdzlismy, ze harry7 sie przyda - wykonajmy na nim operacje\n");
}
}
void comfort_test() throw(exception) {
header("Comfort test - shared_ptr jak zm. auto.; auto. usuwanie, gdy rzucany jest wyjatek");
boost::shared_ptr<Harry> h1;
boost::shared_ptr<Harry> h2;
h1.reset(new Harry("Potter"));
h2.reset(new Harry("Callahan"));
cout << "Callahan count: " << h2.use_count() << endl;
h1 = h2;
cout << "Callahan zjadl Pottera, count: " << h2.use_count() << endl;
cout << "h1: ";
h1->hello();
cout << "h2: ";
h2->hello();
cout << "Throwing an exception .44" << endl;
throw exception();
}
void test_intrusive_ptr() {
header("test_intrusive_ptr");
boost::intrusive_ptr<Intruded> i1(new Intruded);
}
void non_virt_diffs() {
header("Niewirtualny destruktor. Roznice miedzy zwyklym wskaznikiem a shared_ptr");
{
cout << "Zwykly Harry-wskaznik na Betty" << endl;
Harry *hb = new Betty;
delete hb;
}
{
cout << endl << "Betty-wskaznik na Betty w Harry-szablonie" << endl;
boost::shared_ptr<Harry> b1(new Betty);
}
{
cout << endl << "Harry-wskaznik na Betty w Harry-szablonie" << endl;
Harry *b3 = new Betty;
boost::shared_ptr<Harry> b2(b3);
}
}
void play_scoped_array() {
header("Zabawy ze scoped_array");
boost::scoped_array<Harry> harry_a1(new Harry[3]);
}
void general_use() {
header("Ogolny sposob uzycia shared_ptr");
Harry *hp1 = NULL;
boost::shared_ptr<Harry> harry_sp1(hp1 = new Harry("Shared Harry1"));
cout << "harry_sp1.use_count: " << harry_sp1.use_count() << endl;
cout << "Czas, by podzielic sie zasobem" << endl;
boost::shared_ptr<Harry> harry_sp2(harry_sp1);
boost::shared_ptr<Harry> harry_sp3;
harry_sp3 = harry_sp2;
cout << "harry_sp1.use_count: " << harry_sp1.use_count() << endl;
cout << "harry_sp2.use_count: " << harry_sp2.use_count() << endl;
cout << "harry_sp3.use_count: " << harry_sp3.use_count() << endl;
}
SharedHarryVector* get_harries() {
header("Wektor (vector) z Harrych - uzycie shared_ptr w kontenerach STL");
SharedHarryVector *vect = new SharedHarryVector();
boost::shared_ptr<Harry> h;
for(int i = 0; i < 4; ++i) {
h.reset(new Harry("Vector Harry"));
cout << "Ilosc Harry'ego przed wlozeniem do wektora: " << h.use_count() << endl;
vect->push_back(h);
cout << "Po wlozeniu: " << h.use_count() << endl;
}
return vect;
}
void stl_container() {
boost::shared_ptr< SharedHarryVector > harry_vector(get_harries());
cout << "Liczność jednego z wektorowych Harrych: " << harry_vector->front().use_count() << endl << endl;
}
void no_cycle() {
header("Bez cyklu");
boost::shared_ptr<RingNode> R3(new RingNode("RingNode3", boost::shared_ptr<RingNode>((RingNode*)NULL)));
boost::shared_ptr<RingNode> R4(new RingNode("RingNode4", boost::shared_ptr<RingNode>(R3)));
cout << "R3 (" << R4->get_name() << ") with count " << R3.use_count() << endl;
cout << "R4 (" << R4->get_name() << ") with count " << R4.use_count() << " connected to " << R4->get_node()->get_name() << endl;
}
void shared_cycle() {
header("Cykl na shared_ptr");
boost::shared_ptr<RingNode> R7(new RingNode("RingNode7", boost::shared_ptr<RingNode>((RingNode*)NULL)));
boost::shared_ptr<RingNode> R8(new RingNode("RingNode8", boost::shared_ptr<RingNode>(R7)));
boost::shared_ptr<RingNode> R9(new RingNode("RingNode9", boost::shared_ptr<RingNode>(R8)));
R7->connect(R9);
cout << "R7 (" << R7->get_name() << ") with count " << R7.use_count() << " connected to " << R7->get_node()->get_name() << endl;
cout << "R8 (" << R8->get_name() << ") with count " << R8.use_count() << " connected to " << R8->get_node()->get_name() << endl;
cout << "R9 (" << R9->get_name() << ") with count " << R9.use_count() << " connected to " << R9->get_node()->get_name() << endl;
}
void weak_cycle() {
header("Cykl na weak_ptr");
boost::shared_ptr<WeakRingNode> R5(new WeakRingNode("WeakRingNode5", boost::shared_ptr<WeakRingNode>((WeakRingNode*)NULL)));
boost::shared_ptr<WeakRingNode> R6(new WeakRingNode("WeakRingNode6", boost::shared_ptr<WeakRingNode>(R5)));
R5->connect(R6);
boost::weak_ptr<WeakRingNode> Wtmp1(R5);
boost::weak_ptr<WeakRingNode> Wtmp2(R6);
cout << "R5 (" << R5->get_name() << ") with count " << R5.use_count() << " connected to " << R5->get_node()->get_name() << endl;
cout << "R6 (" << R6->get_name() << ") with count " << R6.use_count() << " connected to " << R6->get_node()->get_name() << endl;
}
void shared_and_weak() {
header("Relacja miedzy shared_ptr i weak_ptr");
cout << "Oryginalny shared_ptr:" << endl;
boost::shared_ptr<Harry> shared1(new Harry);
cout << "shared1.count: " << shared1.use_count() << endl;
cout << "weak_ptr z shared_ptr:" << endl;
boost::weak_ptr<Harry> weak1(shared1);
cout << "shared1.count: " << shared1.use_count() << endl;
cout << "weak1.count : " << weak1.use_count() << endl;
cout << "shared_ptr z weak_ptr (z shared_ptr)" << endl;
boost::shared_ptr<Harry> shared2(weak1);
cout << "shared1.count: " << shared1.use_count() << endl;
cout << "weak1.count : " << weak1.use_count() << endl;
cout << "shared2.count: " << shared2.use_count() << endl;
}
void with_sharing_test(WithSharing& ws) {
header("Test enable_shared_from_this<>");
boost::shared_ptr<WithSharing> ws_a(ws.get_shared());
cout << "Drugi udzial, use_count: " << ws_a.use_count() << endl;
boost::shared_ptr<WithSharing> ws_b(ws.get_shared());
cout << "Trzeci udzial, use_count: " << ws_b.use_count() << endl;
}
void auto_ptr_demo() {
header("auto_ptr - przy boost maly sens stosowania");
auto_ptr<Harry> a1(new Harry);
cout << "NEW. " << a1.get() << endl;
auto_ptr<Harry> a2(a1);
cout << "1st transfer, source: " << a1.get() << endl;
cout << "1st transfer, dest. : " << a2.get() << endl;
auto_ptr<Harry> a3 = a2;
cout << "2nd transfer, source: " << a2.get() << endl;
cout << "2nd transfer, dest. : " << a3.get() << endl;
}
int main(int argc, char** argv) {
play_dirty_harry();
general_use();
play_nice_harry();
play_nice_harry3();
play_scoped_array();
non_virt_diffs();
stl_container();
no_cycle();
shared_cycle();
weak_cycle();
shared_and_weak();
try {
comfort_test();
} catch (...) {
cout << "Caught!" << endl;
}
boost::shared_ptr<WithSharing> ws(new WithSharing);
with_sharing_test(*ws);
auto_ptr_demo();
test_intrusive_ptr();
return 0;
}