struct Widget { shared_ptr<Widget> otherWidget; }; void foo() { shared_ptr<Widget> a(new Widget); shared_ptr<Widget> b(new Widget); a->otherWidget = b; // = 2 b->otherWidget = a; // = 2 }
struct RootWidget { list<shared_ptr<class Widget> > widgets; }; struct Widget { shared_ptr<class RootWidget> parent; };
struct Widget { weak_ptr<class RootWidget> parent; };
weak_ptr<Widget> w = …; // , , shared_ptr shared_ptr<Widget> p( w );
weak_ptr<Widget> w = …; // , , p if( shared_ptr<Widget> p = w.lock() ) { // – }
// shared_ptr, foo - foo( shared_ptr<Widget>(new Widget), bar() ); // shared_ptr, foo p shared_ptr<Widget> p(new Widget); foo( p, bar() );
int bar() { throw std::runtime_error(“Exception from bar()”); }
foo( make_shared<Widget>(), bar() );
make_shared<string>("shared string");
shared_ptr<Widget> globalSharedPtr(new Widget); void read() { shared_ptr<Widget> x = globalSharedPtr; // - Widget }
void write() { globalSharedPtr.reset( new Widget ); }
shared_ptr::shared_ptr(const shared_ptr<T>& x) { A1: pointer = x.pointer; A2: counter = x.counter; A3: atomic_increment( *counter ); } shared_ptr<T>::reset(T* newObject) { B1: if( atomic_decrement( *counter ) == 0 ) { B2: delete pointer; B3: delete counter; B4: } B5: pointer = newObject; B6: counter = new Counter; }
shared_ptr<Widget> globalSharedPtr(new Widget); mutex_t globalSharedPtrMutex; void resetGlobal(Widget* x) { write_lock_t l(globalSharedPtrMutex); globalSharedPtr.reset( x ); } shared_ptr<Widget> getGlobal() { read_lock_t l(globalSharedPtrMutex); return globalSharedPtr; } void read() { shared_ptr<Widget> x = getGlobal(); // x } void write() { resetGlobal( new Widget ); }
typedef shared_ptr<Connection> ptr_t; class ConnectionReleaser { list<ptr_t>& whereToReturn; ptr_t connectionToRelease; public: ConnectionReleaser(list<ptr_t>& lst, const ptr_t& x):whereToReturn(lst), connectionToRelease(x) {} void operator()(Connection*) { whereToReturn.push_back( connectionToRelease ); // connectionToRelease.reset(); } }; ptr_t getConnection() { ptr_t c( connectionList.back() ); connectionList.pop_back(); ptr_t r( c.get(), ConnectionReleaser( connectionList, c ) ); return r; }
void releaseConnection(std::list<ptr_t>& whereToReturn, ptr_t& connectionToRelease) { whereToReturn.push_back( connectionToRelease ); // connectionToRelease.reset(); } ptr_t getConnection() { ptr_t c( connectionList.back() ); connectionList.pop_back(); ptr_t r( c.get(), boost::bind(&releaseConnection, boost::ref(connectionList), c) ); return r; }
template<class T> class enable_shared_from_this { weak_ptr<T> weak_this_; public: shared_ptr<T> shared_from_this() { // shared_ptr shared_ptr<T> p( weak_this_ ); return p; } }; class Widget: public enable_shared_from_this<Widget> {};
shared_ptr::shared_ptr(T* object) { pointer = object; counter = new Counter; object->weak_this_ = *this; }
struct BadWidget: public enable_shared_from_this<BadWidget> { BadWidget() { // shared_from_this() bad_weak_ptr cout << shared_from_this() << endl; } };
struct BadWidget: public enable_shared_from_this<BadWidget> { ~BadWidget() { // shared_from_this() bad_weak_ptr cout << shared_from_this() << endl; } };
class GoodWidget: public enable_shared_from_this<GoodWidget> { void init() { cout << shared_from_this() << endl; } public: static shared_ptr<GoodWidget> create() { shared_ptr<GoodWidget> p(new GoodWidget); p->init(); return p; } };
#include <string> #include <iostream> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> class BadWidget { std::string name; boost::shared_ptr<BadWidget> otherWidget; public: BadWidget(const std::string& n):name(n) { std::cout << "BadWidget " << name << std::endl; } ~BadWidget() { std::cout << "~BadWidget " << name << std::endl; } void setOther(const boost::shared_ptr<BadWidget>& x) { otherWidget = x; std::cout << name << " now points to " << x->name << std::endl; } }; class GoodWidget { std::string name; boost::weak_ptr<GoodWidget> otherWidget; public: GoodWidget(const std::string& n):name(n) { std::cout << "GoodWidget " << name << std::endl; } ~GoodWidget() { std::cout << "~GoodWidget " << name << std::endl; } void setOther(const boost::shared_ptr<GoodWidget>& x) { otherWidget = x; std::cout << name << " now points to " << x->name << std::endl; } }; int main() { { // std::cout << "====== Example 3" << std::endl; boost::shared_ptr<BadWidget> w1(new BadWidget("3_First")); boost::shared_ptr<BadWidget> w2(new BadWidget("3_Second")); w1->setOther( w2 ); w2->setOther( w1 ); } { // weak_ptr std::cout << "====== Example 3" << std::endl; boost::shared_ptr<GoodWidget> w1(new GoodWidget("4_First")); boost::shared_ptr<GoodWidget> w2(new GoodWidget("4_Second")); w1->setOther( w2 ); w2->setOther( w1 ); } return 0; }
#include <iostream> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> class Widget {}; int main() { boost::weak_ptr<Widget> w; // weak_ptr // lock std::cout << __LINE__ << ": " << w.lock().get() << std::endl; // shared_ptr try { boost::shared_ptr<Widget> tmp ( w ); } catch (const boost::bad_weak_ptr&) { std::cout << __LINE__ << ": bad_weak_ptr" << std::endl; } boost::shared_ptr<Widget> p(new Widget); // weak_ptr w = p; // lock std::cout << __LINE__ << ": " << w.lock().get() << std::endl; // shared_ptr . std::cout << __LINE__ << ": " << boost::shared_ptr<Widget>( w ).get() << std::endl; // p.reset(); // . weak_ptr // lock std::cout << __LINE__ << ": " << w.lock().get() << std::endl; // shared_ptr try { boost::shared_ptr<Widget> tmp ( w ); } catch (const boost::bad_weak_ptr&) { std::cout << __LINE__ << ": bad_weak_ptr" << std::endl; } return 0; }
#include <iostream> #include <boost/thread.hpp> #include <boost/shared_ptr.hpp> typedef boost::shared_mutex mutex_t; typedef boost::unique_lock<mutex_t> read_lock_t; typedef boost::shared_lock<mutex_t> write_lock_t; mutex_t globalMutex; boost::shared_ptr<int> globalPtr(new int(0)); const int readThreads = 10; const int maxOperations = 10000; boost::shared_ptr<int> getPtr() { // , read_lock_t l(globalMutex); return globalPtr; } void resetPtr(const boost::shared_ptr<int>& x) { // , write_lock_t l(globalMutex); globalPtr = x; } void myRead() { for(int i = 0; i < maxOperations; ++i) { boost::shared_ptr<int> p = getPtr(); } } void myWrite() { for(int i = 0; i < maxOperations; ++i) { resetPtr( boost::shared_ptr<int>( new int(i)) ); } } int main() { boost::thread_group tg; tg.create_thread( &myWrite ); for(int i = 0; i < readThreads; ++i) { tg.create_thread( &myRead ); } tg.join_all(); return 0; }
#include <string> #include <list> #include <iostream> #include <stdexcept> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/bind.hpp> class Connection { std::string name; public: const std::string& getName() const { return name; } explicit Connection(const std::string& n):name(n) { std::cout << "Connection " << name << std::endl; } ~Connection() { std::cout << "~Connection " << name << std::endl; } }; typedef boost::shared_ptr<Connection> ptr_t; class ConnectionPool { std::list<ptr_t> connections; // deleter (get1) class ConnectionReleaser { std::list<ptr_t>& whereToReturn; ptr_t connectionToRelease; public: ConnectionReleaser(std::list<ptr_t>& lst, const ptr_t& x):whereToReturn(lst), connectionToRelease(x) {} void operator()(Connection*) { whereToReturn.push_back( connectionToRelease ); std::cout << "get1: Returned connection " << connectionToRelease->getName() << " to the list" << std::endl; // . connectionToRelease.reset(); } }; // deleter (get2) static void releaseConnection(std::list<ptr_t>& whereToReturn, ptr_t& connectionToRelease) { whereToReturn.push_back( connectionToRelease ); std::cout << "get2: Returned connection " << connectionToRelease->getName() << " to the list" << std::endl; // connectionToRelease.reset(); } ptr_t popConnection() { if( connections.empty() ) throw std::runtime_error("No connections left"); ptr_t w( connections.back() ); connections.pop_back(); return w; } public: ptr_t get1() { ptr_t w = popConnection(); std::cout << "get1: Taken connection " << w->getName() << " from list" << std::endl; ptr_t r( w.get(), ConnectionReleaser( connections, w ) ); return r; } ptr_t get2() { ptr_t w = popConnection(); std::cout << "get2: Taken connection " << w->getName() << " from list" << std::endl; ptr_t r( w.get(), boost::bind(&releaseConnection, boost::ref(connections), w )); return r; } void add(const std::string& name) { connections.push_back( ptr_t(new Connection(name)) ); } ConnectionPool() { std::cout << "ConnectionPool" << std::endl; } ~ConnectionPool() { std::cout << "~ConnectionPool" << std::endl; } }; int main() { boost::weak_ptr<Connection> weak1; boost::weak_ptr<Connection> weak2; { ConnectionPool cp; cp.add("One"); cp.add("Two"); ptr_t p1 = cp.get1(); weak1 = p1; ptr_t p2 = cp.get2(); weak2 = p2; } std::cout << "Here the ConnectionPool is out of scope, but weak_ptrs are not" << std::endl; return 0; }
#include <iostream> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> class BadWidget1: public boost::enable_shared_from_this<BadWidget1> { public: BadWidget1() { std::cout << "Constructor" << std::endl; std::cout << shared_from_this() << std::endl; } }; class BadWidget2: public boost::enable_shared_from_this<BadWidget2> { public: ~BadWidget2() { std::cout << "Destructor" << std::endl; std::cout << shared_from_this() << std::endl; } }; class GoodWidget: public boost::enable_shared_from_this<GoodWidget> { GoodWidget() {} void init() { std::cout << "init()" << std::endl; std::cout << shared_from_this() << std::endl; } public: static boost::shared_ptr<GoodWidget> create() { boost::shared_ptr<GoodWidget> p(new GoodWidget); p->init(); return p; } }; int main() { boost::shared_ptr<GoodWidget> good = GoodWidget::create(); try { boost::shared_ptr<BadWidget1> bad1(new BadWidget1); } catch( const boost::bad_weak_ptr&) { std::cout << "Caught bad_weak_ptr for BadWidget1" << std::endl; } try { boost::shared_ptr<BadWidget2> bad2(new BadWidget2); // terminate // .. , } catch( const boost::bad_weak_ptr&) { std::cout << "Caught bad_weak_ptr for BadWidget2" << std::endl; } return 0; }
Source: https://habr.com/ru/post/191018/
All Articles