以äžã«ã€ããŠã話ããŸãã
- çžäºåç §ãšã¯
- å±éºãªååã®ãªãshared_ptrãšã¯äœã§ããã
- ãã«ãã¹ã¬ããç°å¢ã§shared_ptrã䜿çšããå Žåãã©ã®ãããªå±éºãåŸ ã£ãŠããŸããã
- shared_ptrã®ç¬èªã®ãªãªãŒã¹é¢æ°ãäœæããéã«èŠããŠããã¹ãéèŠãªããš;
- enable_shared_from_thisãã³ãã¬ãŒãã䜿çšããæ©èœã¯äœã§ããã
説æãããŠããåé¡ã¯ãboost :: shared_ptrãšstd :: shared_ptrã®äž¡æ¹ã§çºçããŸãã èšäºã®æåŸã«ãèšè¿°ãããæ©èœãå®èšŒããããã«æžãããããã°ã©ã ã®å šæãå«ãã¢ããªã±ãŒã·ã§ã³ããããŸãïŒäŸãšããŠboostã©ã€ãã©ãªã䜿çšïŒã
çžäºåç §
ãã®åé¡ã¯æãæåã§ãããshared_ptrãã€ã³ã¿ãŒãåç §ã«ãŠã³ãã«åºã¥ããŠããããã§ãã shared_ptrãææãããªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã®å Žåãã«ãŠã³ã¿ãŒãäœæãããŸãã ãã®ã«ãŠã³ã¿ãŒã¯ããã®ãªããžã§ã¯ããæããã¹ãŠã®shared_ptrã«å ±éã§ãã
æ°ãããªããžã§ã¯ããäœæãããšãã«ãŠã³ã¿ãŒãæã€ãªããžã§ã¯ããäœæããããã®äžã«å€1ãé 眮ãããŸããã³ããŒãããšãã«ãŠã³ã¿ãŒã1ãã€å¢å ããŸãã
äŸãèããŠã¿ãŸãããïŒ
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 }
ãªããžã§ã¯ãaãšbãã¹ã³ãŒãããåºããšã©ããªããŸããïŒ ãã¹ãã©ã¯ã¿ã§ã¯ããªããžã§ã¯ããžã®åç §ãæžå°ããŸãã åãªããžã§ã¯ãã«ã¯ãã«ãŠã³ã¿ãŒ= 1ããããŸãïŒçµå±ãaã¯bãæããbã¯aãæããŸãïŒã ãªããžã§ã¯ãã¯ãäºãããä¿æãããã¢ããªã±ãŒã·ã§ã³ã¯ãããã«ã¢ã¯ã»ã¹ããæ©äŒããããŸãã-ãããã®ãªããžã§ã¯ãã¯ã倱ãããŸããã
ãã®åé¡ã解決ããweak_ptrããããŸãã å žåçãªçžäºåç §ã®ã±ãŒã¹ã®1ã€ã¯ã1ã€ã®ãªããžã§ã¯ããä»ã®ãªããžã§ã¯ãã®ã³ã¬ã¯ã·ã§ã³ãææããŠããå Žåã§ãã
struct RootWidget { list<shared_ptr<class Widget> > widgets; }; struct Widget { shared_ptr<class RootWidget> parent; };
ãã®ãããªããã€ã¹ã§ã¯ãåãŠã£ãžã§ããã¯ã«ãŒããŠã£ãžã§ããã®åé€ãé²ããéãåæ§ã§ãã
ãã®å Žåãã誰ã誰ãææããŠããŸããïŒããšãã質åã«çããå¿ èŠããããŸãã æããã«ããŠã£ãžã§ãããªããžã§ã¯ããææããã®ã¯ãã®å Žåã¯RootWidgetã§ããããã®éã§ã¯ãããŸããã ãããã£ãŠã次ã®ããã«äŸãå€æŽããå¿ èŠããããŸãã
struct Widget { weak_ptr<class RootWidget> parent; };
匱ããªã³ã¯ã¯ããªããžã§ã¯ãã®åé€ã劚ããŸããã ãããã¯ã2ã€ã®æ¹æ³ã§åŒ·ãã«å€æã§ããŸãã
1ïŒã³ã³ã¹ãã©ã¯ã¿ãŒshared_ptr
weak_ptr<Widget> w = âŠ; // , , shared_ptr shared_ptr<Widget> p( w );
2ïŒããã¯æ¹æ³
weak_ptr<Widget> w = âŠ; // , , p if( shared_ptr<Widget> p = w.lock() ) { // â }
çµè«ïŒ
ã³ãŒãå ã®ãªã³ã°åç §ã®å Žåãweak_ptrã䜿çšããŠåé¡ã解決ããŸãã
ååã®ãªããã€ã³ã¿ãŒ
ååã®ãªããã€ã³ã¿ãŒã®åé¡ã¯ããã·ãŒã±ã³ã¹ãã€ã³ããã®åé¡ãæããŸãã
// shared_ptr, foo - foo( shared_ptr<Widget>(new Widget), bar() ); // shared_ptr, foo p shared_ptr<Widget> p(new Widget); foo( p, bar() );
ãããã®2ã€ã®ãªãã·ã§ã³ã®ãã¡ãããã¥ã¡ã³ãã§ã¯ãåžžã«2çªç®ã®ååã䜿çšããããšãæšå¥šããŠããŸãã baré¢æ°ã次ã®ããã«å®çŸ©ãããŠããäŸãèããŠã¿ãŸãããã
int bar() { throw std::runtime_error(âException from bar()â); }
å®éã«ã¯ãæåã®ã±ãŒã¹ã§ã¯ãèšèšé åºã¯å®çŸ©ãããŠããŸããã ããã¯ãã¹ãŠãç¹å®ã®ã³ã³ãã€ã©ãšã³ã³ãã€ã«ãã©ã°ã«äŸåããŸãã ããšãã°ãããã¯æ¬¡ã®ããã«çºçããŸãã
- æ°ãããŠã£ãžã§ãã
- ããŒé¢æ°åŒã³åºã
- shared_ptrã®æ§ç¯
- fooé¢æ°åŒã³åºã
fooã®åŒã³åºããæåŸã®ã¢ã¯ã·ã§ã³ã«ãªãããªããžã§ã¯ãïŒæ°ãããŠã£ãžã§ããïŒã®äœæåŸã«shared_ptrãæ§ç¯ãããããšã®ã¿ã確èªã§ããŸãã ãã ãããªããžã§ã¯ãã®äœæçŽåŸã«æ§ç¯ããããšããä¿èšŒã¯ãããŸããã
2çªç®ã®ã¹ãããã§äŸå€ãã¹ããŒãããå ŽåïŒãã®äŸã§ã¯ã¹ããŒãããŸãïŒããŠã£ãžã§ããã¯æ§ç¯ããããšèŠãªãããŸãããshared_ptrã¯ãŸã ãããææããŠããŸããã ãã®çµæããã®ãªããžã§ã¯ããžã®ãªã³ã¯ã¯å€±ãããŸãã ãã®äŸãgcc 4.7.2ã§ãã¹ãããŸããã åŒã³åºãã®é åºã¯ãå ±æãªãã·ã§ã³ã«é¢ä¿ãªããshared_ptr + newãbarã®åŒã³åºãã«ãã£ãŠåé¢ãããªããããªãã®ã§ããã ãããããã®ãããªæ¯ãèãã ãã«é Œã䟡å€ã¯ãããŸãã-ä¿èšŒãããŠããŸããã ã³ã³ãã€ã©ãããŒãžã§ã³ãããã³ãã®ãããªã³ãŒãããšã©ãŒã«ã€ãªããã³ã³ãã€ã«ãªãã·ã§ã³ãæããŠãããã°ãããããã§ãã
å¿åã®shared_ptråé¡ãåé¿ããå¥ã®æ¹æ³ã¯ãmake_sharedãŸãã¯allocate_sharedé¢æ°ã䜿çšããããšã§ãã ãã®äŸã§ã¯ã次ã®ããã«ãªããŸãã
foo( make_shared<Widget>(), bar() );
ãã®äŸã¯ãå ã®äŸãããç°¡æœã«èŠããã ãã§ãªããã¡ã¢ãªã®å²ãåœãŠã«é¢ããŠå€ãã®å©ç¹ããããŸãïŒå¹çã®åé¡ã¯èšäºã®ç¯å²å€ã«ããŸãïŒã ä»»æã®æ°ã®åŒæ°ãæå®ããŠmake_sharedãåŒã³åºããŸãããã ããšãã°ã次ã®ã³ãŒãã¯ã1ã€ã®ãã©ã¡ãŒã¿ãŒãæã€ã³ã³ã¹ãã©ã¯ã¿ãŒã«ãã£ãŠäœæãããæååã«shared_ptrãè¿ããŸãã
make_shared<string>("shared string");
çµè«ïŒ
ã³ãŒããããããç°¡æœã§ãªãå Žåã§ãshared_ptråãä»ãããããªããžã§ã¯ãã®äœæã«äœ¿çšããŸã
make_sharedããã³allocate_sharedé¢æ°ã
ç°ãªãã¹ã¬ããã§äœ¿çšããåé¡
shared_ptrã®ãªã³ã¯ã«ãŠã³ãã¯ãã¢ãããã¯ã«ãŠã³ã¿ãŒã䜿çšããŠæ§ç¯ãããŸãã ç°ãªãã¹ã¬ããããåããªããžã§ã¯ããžã®ãã€ã³ã¿ãå®å šã«äœ¿çšããŸãã ãããã«ãããåç §ã«ãŠã³ããå¿é ããããšã«æ £ããŠããŸããïŒãªããžã§ã¯ãèªäœã®ã¹ã¬ããã»ãŒãã¯å¥ã®åé¡ã§ãïŒã
ã°ããŒãã«ãªshared_ptrããããšããŸãïŒ
shared_ptr<Widget> globalSharedPtr(new Widget); void read() { shared_ptr<Widget> x = globalSharedPtr; // - Widget }
ç°ãªãã¹ã¬ããããèªã¿åãåŒã³åºããå®è¡ãããšãã³ãŒãã«åé¡ããªãããšãããããŸãïŒãŠã£ãžã§ããã§ãã®ã¯ã©ã¹ã®ã¹ã¬ããã»ãŒãæäœãå®è¡ããŠããå ŽåïŒã
å¥ã®é¢æ°ããããšä»®å®ããŸãã
void write() { globalSharedPtr.reset( new Widget ); }
shared_ptrããã€ã¹ã¯éåžžã«è€éãªã®ã§ãåé¡ãæš¡åŒçã«ç€ºãã³ãŒããæäŸããŸãã ãã¡ããããã®ã³ãŒãã¯ç°ãªã£ãŠèŠããŸãã
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; }
æåã®ã¹ã¬ãããglobalSharedPtrïŒèªã¿åãïŒã®ã³ããŒãéå§ãã2çªç®ã®ã¹ã¬ãããåããã€ã³ã¿ãŒã€ã³ã¹ã¿ã³ã¹ïŒãªã»ããïŒã«å¯ŸããŠresetãåŒã³åºãããšããŸãã çµæã¯æ¬¡ã®ããã«ãªããŸãã
- ã¹ã¬ãã1ã¯è¡A2ãå®äºããŸãããããŸã è¡A3ã«ç§»åããŠããŸããïŒã¢ãããã¯å¢åïŒã
- ãã®æç¹ã§Stream2ã¯ãã©ã€ã³B1ã®ã«ãŠã³ã¿ãŒãæžãããã«ãŠã³ã¿ãŒãæžãããåŸãã«ãŠã³ã¿ãŒããŒãã«ãªããã©ã€ã³B2ãšB3ãå®äºããããšã確èªããŸããã
- Thread1ã¯è¡A3ã«å°éãããã§ã«ãªããªã£ãŠããã«ãŠã³ã¿ãŒãã¢ãããã¯ã«å¢å ãããããšããŸãã
ãŸãã¯ãè¡A2ã®stream1ã«ã¯ãstream2ããªããžã§ã¯ããåé€ããåã«ãstream2ãã«ãŠã³ãããŠã³ããåŸã«ã«ãŠã³ã¿ãŒãã€ã³ã¯ãªã¡ã³ãããæéããããŸãã 次ã«ããªã¢ãŒãã«ãŠã³ã¿ãŒãšãªããžã§ã¯ããæãæ°ããshared_ptrãååŸããŸãã
åæ§ã®ã³ãŒããæžãããšãã§ããŸãïŒ
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 ); }
ããã§ããã®ãããªé¢æ°ã䜿çšããŠããã®shared_ptrãå®å šã«æäœã§ããŸãã
çµè«ïŒããã€ãã®shared_ptrã€ã³ã¹ã¿ã³ã¹ãç°ãªãã¹ã¬ããã§å©çšå¯èœã§ãããå€æŽã§ããå Žåããã®shared_ptrã€ã³ã¹ã¿ã³ã¹ãžã®ã¢ã¯ã»ã¹ãåæãããå¿ èŠããããŸãã
shared_ptrã®ãªãªãŒã¹ãã¡ã³ã¯ã¿ãŒã®ç Žæ£æéã®ç¹æ§
ãã®åé¡ã¯ãç¬èªã®ãªãªãŒã¹ãã¡ã³ã¯ã¿ãŒã匱ããã€ã³ã¿ãŒïŒweak_ptrïŒãšçµã¿åãããŠäœ¿çšââããå Žåã«ã®ã¿çºçããŸãã ããšãã°ãåé€åã«æ°ããã¢ã¯ã·ã§ã³ãè¿œå ããããšã§ãå¥ã®shared_ptrã«åºã¥ããŠshared_ptrãäœæã§ããŸãïŒåºæ¬çã«ã¯ãDecoratorããã³ãã¬ãŒãïŒã ãããã£ãŠãæ¥ç¶ããŒã«ããããŒã¿ããŒã¹ãåé€ããããšã§ãããŒã¿ããŒã¹ãæäœããããã®ãã€ã³ã¿ãŒãååŸããã¯ã©ã€ã¢ã³ãããã€ã³ã¿ãŒã®æäœãçµäºããããããŒã«ã«æ»ãããšãã§ããŸãã
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; }
åé¡ã¯ãshared_ptrã®ãªãªãŒã¹ãã¡ã³ã¯ã¿ãšããŠæž¡ããããªããžã§ã¯ãã¯ããªããžã§ã¯ããžã®ãã¹ãŠã®åç §ãç Žæ£ããããšãã«ã®ã¿ç Žæ£ãããããšã§ã-匷ãïŒshared_ptrïŒãšåŒ±ãïŒweak_ptrïŒã®äž¡æ¹ã§ãã ãããã£ãŠãConnectionReleaserãæž¡ããããã€ã³ã¿ãŒãã解æŸãããããšã«æ³šæããªãå ŽåïŒconnectionToReleaseïŒãgetConnectioné¢æ°ã«ãã£ãŠäœæãããshared_ptrããå°ãªããšã1ã€ã®weak_ptrãããéãã匷åãªãªã³ã¯ãä¿æããŸãã ããã¯ãã¢ããªã±ãŒã·ã§ã³ã®éåžžã«äžå¿«ã§äºæããªãåäœãåŒãèµ·ããå¯èœæ§ããããŸãã
ãŸãããã€ã³ãã䜿çšããŠãªãªãŒã¹ãã¡ã³ã¯ã¿ãäœæããããšãã§ããŸãã ããšãã°ã次ã®ããã«ïŒ
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; }
bindã¯æž¡ãããåŒæ°ãã³ããŒããããšã«æ³šæããŠãã ããïŒboost :: refã䜿çšããå Žåãé€ãïŒããããã®éã«shared_ptrãããå Žåã¯ãæ¢ã«èª¬æããåé¡ãåé¿ããããã«ã¯ãªã¢ããå¿ èŠããããŸãã
çµè«ïŒãªãªãŒã¹æ©èœã§ãæåŸã®åŒ·åãªãªã³ã¯ãåæãããšãã«å®è¡ããå¿ èŠããããã¹ãŠã®ã¢ã¯ã·ã§ã³ãå®è¡ããŸãã äœããã®çç±ã§ãã¡ã³ã¯ã¿ãŒã®ã¡ã³ããŒã§ãããã¹ãŠã®shared_ptrããªã»ããããŸãã ãã€ã³ãã䜿çšããå Žåãæž¡ãããåŒæ°ãã³ããŒããããšãå¿ããªãã§ãã ããã
enable_shared_from_thisãã³ãã¬ãŒãã䜿çšããæ©èœ
ãªããžã§ã¯ãèªäœã®ã¡ãœããããshared_ptrãååŸããå¿ èŠãããå ŽåããããŸãã ããããæ°ããshared_ptrãäœæããããšãããšããããäžè¬çãªæ £ç¿ã§ããintrusive_ptrãšã¯ç°ãªããæªå®çŸ©ã®åäœïŒããã°ã©ã ãã¯ã©ãã·ã¥ãããå¯èœæ§ãæãé«ãïŒã«ã€ãªãããŸãã ãã®åé¡ã解決ããããã«ããã³ãã¬ãŒãæ··åã¯ã©ã¹enable_shared_from_thisãçºæãããŸããã
enable_shared_from_thisãã³ãã¬ãŒãã®æ§é ã¯æ¬¡ã®ãšããã§ããã¯ã©ã¹ã«ã¯weak_ptrãå«ãŸããŸããããã¯ãshared_ptrãäœæãããšãã«ããã®shared_ptrãžã®åç §ãå«ã¿ãŸãã ãªããžã§ã¯ãã®shared_from_thisã¡ãœãããåŒã³åºããšãweak_ptrã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãä»ããŠshared_ptrã«å€æãããŸãã æŠç¥çã«ã¯ããã³ãã¬ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
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::shared_ptr(T* object) { pointer = object; counter = new Counter; object->weak_this_ = *this; }
ãªããžã§ã¯ããæ§ç¯ãããšããweak_this_ã¯ãŸã äœã瀺ããªãããšãç解ããããšãéèŠã§ãã æ§ç¯ããããªããžã§ã¯ããshared_ptrã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããåŸã«ã®ã¿ãæ£ãããªã³ã¯ã衚瀺ãããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒããshared_from_thisãåŒã³åºãããšãããšãbad_weak_pträŸå€ãã¹ããŒãããŸãã
struct BadWidget: public enable_shared_from_this<BadWidget> { BadWidget() { // shared_from_this() bad_weak_ptr cout << shared_from_this() << endl; } };
ãã¹ãã©ã¯ã¿ãŒããshared_from_thisã«ã¢ã¯ã»ã¹ããããšãããšãåãçµæã«ãªããŸãããå¥ã®çç±ã§ããªããžã§ã¯ãã®ç Žå£æã«ã¯ã匷åãªãªã³ã¯ããããæããŠããªããšæ¢ã«èããããŠããŸãïŒã«ãŠã³ã¿ãŒã¯æžå°ããŸãïŒã
struct BadWidget: public enable_shared_from_this<BadWidget> { ~BadWidget() { // shared_from_this() bad_weak_ptr cout << shared_from_this() << endl; } };
2çªç®ã®ã±ãŒã¹ïŒãã¹ãã©ã¯ã¿ïŒã§ã¯ãã»ãšãã©èããããŸããã å¯äžã®ãªãã·ã§ã³ã¯ãshared_from_thisãåŒã³åºããªãããã«æ³šæãããã¹ãã©ã¯ã¿ãåŒã³åºãé¢æ°ãåŒã³åºããªãããã«ããããšã§ãã
æåã®ã±ãŒã¹ã¯å°ãåçŽã§ãã ãªããžã§ã¯ããååšããå¯äžã®æ¹æ³ã¯shared_ptrã§ãããšæ¢ã«æ±ºå®ããŠããã®ã§ããªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãã¯ã©ã¹ã®ãã©ã€ããŒãéšåã«ç§»åããå¿ èŠãªã¿ã€ãã®shared_ptrãäœæããéçã¡ãœãããäœæããããšãé©åã§ãã ãªããžã§ã¯ãã®åæåäžã«shared_from_thisãå¿ èŠãšããã¢ã¯ã·ã§ã³ãå®è¡ããå¿ èŠãããå Žåããã®ç®çã®ããã«ãinitã¡ãœããã§ããžãã¯ãéžæã§ããŸãã
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; } };
çµè«ïŒ
ã³ã³ã¹ãã©ã¯ã¿ãŒããã³ãã¹ãã©ã¯ã¿ãŒããïŒçŽæ¥ãŸãã¯éæ¥ïŒshared_from_thisãåŒã³åºããªãã§ãã ããã ãªããžã§ã¯ãã®é©åãªåæåã«shared_from_thisãžã®ã¢ã¯ã»ã¹ãå¿ èŠãªå ŽåïŒinitã¡ãœãããäœæãããªããžã§ã¯ãã®äœæãéçã¡ãœããã«å§ä»»ããŠããã®ã¡ãœããã䜿çšããŠã®ã¿ãªããžã§ã¯ããäœæã§ããããã«ããŸãã
ãããã«
ãã®èšäºã§ã¯ãshared_ptrã䜿çšãã5ã€ã®æ©èœã«ã€ããŠèª¬æããæœåšçãªåé¡ãåé¿ããããã®äžè¬çãªæšå¥šäºé ãæäŸããŸãã
shared_ptrã¯éçºè ããå€ãã®åé¡ãåãé€ããŸãããshared_ptrãé©åã«äœ¿çšããã«ã¯ãå éšããã€ã¹ã®ç¥èïŒã»ãŒã§ã¯ãããŸããïŒãå¿ é ã§ãã shared_ptrããã€ã¹ãšããã«é¢é£ããã¯ã©ã¹ãæ éã«æ€èšããããšããå§ãããŸãã ããã€ãã®åçŽãªã«ãŒã«ãé å®ããããšã§ãéçºè ã¯äžèŠãªåé¡ãåé¿ã§ããŸãã
æåŠ
- Boost.orgã®ããã¥ã¡ã³ã
- ã¹ã³ããã»ãã€ã€ãŒãºãããå¹æçãªC ++ïŒããã°ã©ã ãšãã¶ã€ã³ãæ¹åãã35ã®æ°ããæ¹æ³ã
ã¢ããª
ä»é²ã«ã¯ãèšäºã§èª¬æãããŠããã±ãŒã¹ã説æããããã®ããã°ã©ã ã®å šæãå«ãŸããŠããŸãã
ãªã³ã°ãªã³ã¯ã®åé¡ã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³
#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; }
weak_ptrãshared_ptrã«å€æãããã¢
#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; }
shared_ptrã®ãã«ãã¹ã¬ããååé¡ã®ãã¢
#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; }
deleter + weak_ptråé¡ã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³
#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; }
enable_shared_from_thisã®åé¡ã®ãã¢
#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; }