[JCP] class interleaving C++ class std:: string std::vector std::map class MutexLock MutexLockGuard C MutexLock critical section



Similar documents
W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent IO UNIX CPU

W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent UNIX CPU IO

1 C++ 2 Bjarne Stroustrup C++ (system programming) 6 (infrastructure) C++ 7 Herb Sutter 8 C++ (efficiency) (flexibility) 9 (abstraction) (productivity

Scott Effective C++ C++ C++ Roger Orr OR/2 ISO C++ Effective Modern C++ C++ C++ Scoot 42 Bart Vandewoestyne C++ C++ Scott Effective Modern C++ Damien

新版 明解C++入門編

FY.DOC

untitled

提问袁小兵:

概述

设计模式_Patterns in Java_.doc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

c_cpp

Microsoft Word - 物件導向編程精要.doc

EJB-Programming-4-cn.doc

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

C++11概要 ライブラリ編

基于CDIO一体化理念的课程教学大纲设计

<4D F736F F D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

《大话设计模式》第一章

WWW PHP

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

CC213

Java 1 Java String Date

2 2 3 DLight CPU I/O DLight Oracle Solaris (DTrace) C/C++ Solaris DLight DTrace DLight DLight DLight C C++ Fortran CPU I/O DLight AM

新・解きながら学ぶJava

Strings

Microsoft Word - 第3章.doc

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

Microsoft PowerPoint - plan08.ppt

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

Java

第一章 概论

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

Microsoft Word - ch04三校.doc

Microsoft Word - 01.DOC

ebook

文档 3

Microsoft PowerPoint - ch6 [相容模式]

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

不 知 肉 味 的 用 法 相 同? (A) 長 煙 一 空, 皓 月 千 里 (B) 五 臟 六 腑 裡, 像 熨 斗 熨 過, 無 一 處 不 伏 貼 (C) 兩 片 頑 鐵, 到 他 手 裡, 便 有 了 五 音 十 二 律 似 的 (D) 吾 觀 三 代 以 下, 世 衰 道 微 12. 文

C C C The Most Beautiful Language and Most Dangerous Language in the Programming World! C 2 C C C 4 C Project 30 C Project 3 60 Project 40

untitled

untitled

C/C++ - 函数

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

C/C++ - 文件IO

(procedure-oriented)?? 2

untitled


chp6.ppt

Factory Methods

C/C++ - 字符输入输出和字符确认

IoC容器和Dependency Injection模式.doc

epub 32-2

C/C++ - 字符串与字符串函数

新・解きながら学ぶC言語

JBuilder Weblogic

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

软件测试(TA07)第一学期考试

51 C 51 isp 10 C PCB C C C C KEIL

INTRODUCTION TO COM.DOC

ebook39-5

epub83-1

全国计算机技术与软件专业技术资格(水平)考试

Microsoft Word htm

CHAPTER VC#

Chapter 9: Objects and Classes

科学计算的语言-FORTRAN95

新・明解C言語入門編『索引』

ebook66-15

_汪_文前新ok[3.1].doc

PTS7_Manual.PDF

ebook50-15

建模与图形思考

Transcription:

1 synchronization primitives mutex race condition C++ Boost shared_ptr weak_ptr 1 Observer 2009 12 C++ C++ Observer 1.1 C++ race condition race condition C++ shared_ptr C++ 1 class TR1 std::tr1 C++11 3

4 1 1.1.1 [JCP] class interleaving C++ class std:: string std::vector std::map class 1.1.2 MutexLock MutexLockGuard C++ 2.4 MutexLock critical section RAII [CCS 13] Windows struct CRITI- CAL_SECTION Linux pthread_mutex_t 2 MutexLock class MutexLockGuard MutexLockGuard class 2.1 1.1.3 Counter class Counter 1 // A thread-safe counter 2 class Counter : boost::noncopyable 3 4 // copy-ctor and assignment should be private by default for a class. 5 public: 6 Counter() : value_(0) 2 2.1.1

1.2 5 7 int64_t value() const; 8 int64_t getandincrease(); 9 10 private: 11 int64_t value_; 12 mutable MutexLock mutex_; 13 ; 14 15 int64_t Counter::value() const 16 17 MutexLockGuard lock(mutex_); // lock 18 return value_; // 19 20 21 int64_t Counter::getAndIncrease() 22 23 MutexLockGuard lock(mutex_); 24 int64_t ret = value_++; 25 return ret; 26 27 // In a real world, atomic operations are preferred. 28 // class class Counter mutex_ lock contention L24 Counter mutex_ mutable const Counter::value() non-const mutex_ mutex_ static / Counter Counter race condition 1.2 this this this escape

6 1 // Don't do this. class Foo : public Observer // Observer 10 public: Foo(Observable* s) s->register_(this); // virtual void update(); ; // Do this. class Foo : public Observer public: Foo(); virtual void update(); // void observe(observable* s) s->register_(this); ; Foo* pfoo = new Foo; Observable* s = getsubject(); pfoo->observe(s); // s->register_(pfoo); +initialize() C++ initialize() this Foo Foo::Foo() most-derived class

1.3 7 1.3 3 mutex 1.3.1 mutex mutex (1) (2) Foo::~Foo() MutexLockGuard lock(mutex_); // free internal state (1) void Foo::update() MutexLockGuard lock(mutex_); // (2) // make use of internal state A B Foo x A x B x->update() extern Foo* x; // visible by all threads // thread A delete x; x = NULL; // helpless // thread B if (x) x->update(); A NULL B x x race condition 1. A (1) 2. B if (x) (2) mutex_ (2) core dump delete NULL 3 dangling pointer wild pointer http://en.wikipedia.org/wiki/dangling_pointer

8 1 1.3.2 mutex class MutexLock class MutexLock MutexLock 1.1 class swap() void swap(counter& a, Counter& b) MutexLockGuard alock(a.mutex_); MutexLockGuard block(b.mutex_); int64_t value = a.value_; a.value_ = b.value_; b.value_ = value; // potential dead lock A swap(a, b); B swap(b, a); operator=() Counter& Counter::operator=(const Counter& rhs) if (this == &rhs) return *this; MutexLockGuard mylock(mutex_); // potential dead lock MutexLockGuard itslock(rhs.mutex_); value_ = rhs.value_; // value_ = rhs.value() return *this; mutex mutex 1.4 Observer

1.4 Observer 9 [CCS 99] free(3) C/C++ 4 composition aggregation association composition / x owner owner x x owner scoped_ptr owner C++ association / a b a b b a aggregation association a b b 1.1 A x B x lock contention x x race condition 4 Java reference null

10 1 Observer recipes/thread/test/observer.cc 1 class Observer // : boost::noncopyable 2 3 public: 4 virtual ~Observer(); 5 virtual void update() = 0; 6 //... 7 ; 8 9 class Observable // : boost::noncopyable 10 11 public: 12 void register_(observer* x); 13 void unregister(observer* x); 14 15 void notifyobservers() 16 for (Observer* x : observers_) // C++11 17 x->update(); // (3) 18 19 20 private: 21 std::vector<observer*> observers_; 22 ; Observable Observer (L17) Observer x Observer unregister() 23 class Observer 24 25 // 26 void observe(observable* s) 27 s->register_(this); 28 subject_ = s; 29 30 31 virtual ~Observer() 32 subject_->unregister(this); 33 34 35 Observable* subject_; 36 ; Observer unregister(this) race conditions L32 subject_ subject_ 1. A L32 unregister 2. B L17 x L32

1.5 11 x Observer 5 Observer L32 core dump race condition isalive() 1.5 raw pointer Observable Observer* Observer Observer race condition subject_ Observable* C++ shared_ptr p1 p2 Object p1 p2 1-1 A p1 p1 NULL p2 1-1 C/C++ p1 p2 Object p1=0 p2 Object 1-1 5 C++

12 1 p1 p2 1-2 proxy Object C p1 p2 p1 proxy Object p2 1-2 Object proxy 0 1-3 p2 proxy Object p1=0 proxy=0 Object p2 1-3 Object race condition p2 proxy Object p1 proxy proxy reference counting p1 p2 sp1 sp2 proxy 1. 2 1-4 sp1 sp2 pointer count = 2 1-4 Object

1.6 shared_ptr/weak_ptr 13 2. sp1 1 1-5 sp1 sp2 pointer count = 1 1-5 Object 3. sp2 0 proxy Object 1-6 sp1 sp2 pointer count = 0 1-6 Object another layer of indirection 6 Object handle/body idiom handle 7 C++ TR1 1.6 shared_ptr/weak_ptr shared_ptr Boost std::tr1 C++11 C++ shared_ptr<t> class template 6 http://en.wikipedia.org/wiki/abstraction_layer 7 Edsger W. Dijkstra The Humble Programmer http://www.cs.utexas.edu/~ewd/transcriptions/ewd03xx/ewd340.html

14 1 0 weak_ptr weak shared_ptr shared_ptr shared_ptr x shared_ptr x x shared_ptr reset() x weak_ptr promote shared_ptr shared_ptr /lock() shared_ptr/weak_ptr shared_ptr/weak_ptr std::string STL 8 C++ clean up 1.7 9 C Nginx C 10 C++ 2004 C++ 8 http://blog.csdn.net/myan/article/details/1906 9 Java C http://blog.csdn.net/myan/article/details/1482614 10 http://trac.nginx.org/nginx/ticket/134,135,162

1.7 15 C++ 1. buffer overrun 2. / 3. double delete 4. memory leak 5. new[]/delete 6. memory fragmentation 5 6 9.2.1 A.1.8 1. std::vector<char>/std::string Buffer class 2. / shared_ptr/weak_ptr 3. scoped_ptr 4. scoped_ptr 5. new[]/delete new[] std::vector/scoped_array std:: vector/std::list std::string C++ delete security data safety scoped_ptr/shared_ptr/weak_ptr shared_ptr<foo>* pfoo = new shared_ptr<foo>(new Foo); // WRONG semantic x T incomplete x.cpp 10.3.2

16 1 1.8 Observer weak_ptr Observer Observable weak_ptr<observer> recipes/thread/test/observer_safe.cc 39 class Observable // not 100% thread safe! 40 41 public: 42 void register_(weak_ptr<observer> x); // const weak_ptr<observer>& 43 // void unregister(weak_ptr<observer> x); // 44 void notifyobservers(); 45 46 private: 47 mutable MutexLock mutex_; 48 std::vector<weak_ptr<observer> > observers_; 49 typedef std::vector<weak_ptr<observer> >::iterator Iterator; 50 ; 51 52 void Observable::notifyObservers() 53 54 MutexLockGuard lock(mutex_); 55 Iterator it = observers_.begin(); // Iterator 49 56 while (it!= observers_.end()) 57 58 shared_ptr<observer> obj(it->lock()); // 59 if (obj) 60 61 // 2 62 obj->update(); // obj 63 ++it; 64 65 else 66 67 // weak_ptr 68 it = observers_.erase(it); 69 70 71 recipes/thread/test/observer_safe.cc (3) p. 10 L17 L48 vector<shared_ptr<observer> > observers_; Observer* weak_ptr<observer> Observer 1.14

1.9 shared_ptr 17 Observer shared_ptr Observer subject_->unregister(this) subject_ Observable shared_ptr subject_ weak_ptr<observable> lock contention Observable register_() unregister() notifyobservers() update() register_() unregister() L62 update() (un)register mutex_ mutex_ core dump vector observers_ mutex_ std::list ++it mutex Pthreads mutex 2.1.1 Java intrinsic lock synchronized synchronized 1.9 shared_ptr shared_ptr shared_ptr 100% shared_ptr 11 shared_ptr std::string shared_ptr shared_ptr shared_ptr shared_ptr 11 http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#threadsafety

18 1 shared_ptr mutex MutexLock mutex; // No need for ReaderWriterLock shared_ptr<foo> globalptr; // globalptr doit() void doit(const shared_ptr<foo>& pfoo); globalptr globalptr void read() shared_ptr<foo> localptr; MutexLockGuard lock(mutex); localptr = globalptr; // read globalptr // use localptr since here localptr doit(localptr); void write() shared_ptr<foo> newptr(new Foo); // MutexLockGuard lock(mutex); globalptr = newptr; // write to globalptr // use newptr since here newptr doit(newptr); read() write() globalptr Foo shared_ptr local copy local copy shared_ptr reference to const new Foo globalptr.reset(new Foo) globalptr.reset() localptr globalptr swap() write() globalptr = newptr; globalptr Foo

1.10 shared_ptr 19 1.10 shared_ptr shared_ptr x shared_ptr shared_ptr p. 16 L48 observers_ vector<shared_ ptr<observer> > unregister() Observer unregister() unregister() Observer Java boost::bind boost::bind shared_ptr boost::function class Foo void doit(); ; shared_ptr<foo> pfoo(new Foo); boost::function<void()> func = boost::bind(&foo::doit, pfoo); // long life foo func shared_ptr<foo> Foo shared_ptr const reference const reference shared_ptr Foo void save(const shared_ptr<foo>& pfoo); void validateaccount(const Foo& foo); bool validate(const shared_ptr<foo>& pfoo) validateaccount(*pfoo); //... // pass by const reference // pass by const reference pass by const reference void onmessage(const string& msg) shared_ptr<foo> pfoo(new Foo(msg)); // if (validate(pfoo)) // pfoo save(pfoo); // pfoo

20 1 shared_ptr pfoo shared_ptr<void> shared_ptr DLL A B Foo Foo inline Foo Factory shared_ptr shared_ptr<t> functor Scott Meyers 12 x shared_ptr x shared_ptr BlockingQueue<shared_ptr<void> > RAII handle RAII C++ RAII C++ C++ C++ new delete new delete RAII [CCS 13] new handle shared_ptr delete shared_ptr owner child shared_ptr child owner weak_ptr 12 http://www.artima.com/cppsource/top_cpp_aha_moments.html

1.11 21 1.11 Stock Google key "NASDAQ:GOOG" IBM "NYSE:IBM" Stock Stock Stock Stock StockFactory 13 key Stock shared_ptr // version 1: questionable code class StockFactory : boost::noncopyable public: shared_ptr<stock> get(const string& key); private: mutable MutexLock mutex_; std::map<string, shared_ptr<stock> > stocks_; ; get() stocks_ key stocks_[key] Stock stocks_[key] Stock map shared_ptr Observable weak_ptr // // version 2: std::map<string, weak_ptr<stock> > stocks_; shared_ptr<stock> StockFactory::get(const string& key) shared_ptr<stock> pstock; MutexLockGuard lock(mutex_); weak_ptr<stock>& wkstock = stocks_[key]; // key pstock = wkstock.lock(); // if (!pstock) pstock.reset(new Stock(key)); wkstock = pstock; // stocks_[key] wkstock return pstock; 13 recipes/thread/test/factory.cc

22 1 Stock stocks_ stocks_.size() Stock Stock 0 key shared_ptr shared_ptr d d(ptr) ptr shared_ptr shared_ptr bridge template<class Y, class D> shared_ptr::shared_ptr(y* p, D d); template<class Y, class D> void shared_ptr::reset(y* p, D d); // Y T Y* T* Stock stocks_ // version 3 class StockFactory : boost::noncopyable // get() pstock.reset(new Stock(key)); // pstock.reset(new Stock(key), // boost::bind(&stockfactory::deletestock, this, _1)); // *** private: void deletestock(stock* stock) if (stock) MutexLockGuard lock(mutex_); stocks_.erase(stock->key()); delete stock; // sorry, I lied // assuming StockFactory lives longer than all Stock's... //... pstock.reset() boost::function Stock* p StockFactory deletestock StockFactory this boost::function *** Stock- Factory Stock core dump Observer Observable::unregister() Observable

1.11 23 1.11.2 1.11.1 enable_shared_from_this StockFactory::get() this boost::function *** StockFactory Stock Stock StockFactory::deleteStock core dump shared_ptr StockFactory::get() shared_ptr<stockfactory> enable_shared_from_this 14 this shared_ptr class StockFactory : public boost::enable_shared_from_this<stockfactory>, boost::noncopyable /*... */ ; shared_from_this() StockFactory stack object heap object shared_ptr shared_ptr<stockfactory> stockfactory(new StockFactory); this shared_ptr<stockfactory> // version 4 shared_ptr<stock> StockFactory::get(const string& key) // change // pstock.reset(new Stock(key), // boost::bind(&stockfactory::deletestock, this, _1)); // to pstock.reset(new Stock(key), boost::bind(&stockfactory::deletestock, shared_from_this(), _1)); //... boost::function shared_ptr<stockfactory> StockFactory::deleteStock StockFactory shared_from_this() StockFactory shared_ptr StockFactory 14 http://en.wikipedia.org/wiki/curiously_recurring_template_pattern

24 1 1.11.2 shared_ptr boost::bind boost:function Stock- Factory boost:function Observable::notifyObservers() weak_ptr weak_ptr boost::function shared_ptr StockFactory class StockFactory : public boost::enable_shared_from_this<stockfactory>, boost::noncopyable public: shared_ptr<stock> get(const string& key) shared_ptr<stock> pstock; MutexLockGuard lock(mutex_); weak_ptr<stock>& wkstock = stocks_[key]; // wkstock pstock = wkstock.lock(); if (!pstock) pstock.reset(new Stock(key), boost::bind(&stockfactory::weakdeletecallback, boost::weak_ptr<stockfactory>(shared_from_this()), _1)); // shared_from_this() weak_ptr // boost::bind wkstock = pstock; return pstock; private: static void weakdeletecallback(const boost::weak_ptr<stockfactory>& wkfactory, Stock* stock) shared_ptr<stockfactory> factory(wkfactory.lock()); // if (factory) // factory stocks_ factory->removestock(stock); delete stock; // sorry, I lied

1.11 25 void removestock(stock* stock) if (stock) MutexLockGuard lock(mutex_); stocks_.erase(stock->key()); private: mutable MutexLock mutex_; std::map<string, weak_ptr<stock> > stocks_; ; void testlonglifefactory() shared_ptr<stockfactory> factory(new StockFactory); shared_ptr<stock> stock = factory->get("nyse:ibm"); shared_ptr<stock> stock2 = factory->get("nyse:ibm"); assert(stock == stock2); // stock destructs here // factory destructs here void testshortlifefactory() shared_ptr<stock> stock; shared_ptr<stockfactory> factory(new StockFactory); stock = factory->get("nyse:ibm"); shared_ptr<stock> stock2 = factory->get("nyse:ibm"); assert(stock == stock2); // factory destructs here // stock destructs here Stock StockFactory shared_ptr weak_ptr Factory singleton 15 StockFactory Stock stocks_ 2.1 2.8 15 recipes/thread/weakcallback.h C++11 variadic template rvalue reference

26 1 1.12 shared_ptr/weak_ptr C++ 1. façade Foo Foo façade objid/handle check-out check-in 16 race condition façade Foo Java ConcurrentHashMap buckets bucket contention 2. 1.4 3. 17 shared_ptr shared_ptr 4. C++11 unique_ptr shared_ptr Google Go Concurrency is hard without garbage collection C/C++ Java util.concurrent C++11 1.13 API 16 Jeff Grossman A technique for safe deletion with object locking [Gr00] 17 http://blog.csdn.net/solstice/article/details/5238671#comments

1.13 27 18 1.9 shared_ptr C++ C Java Java Concurrency in Practice [JCP] C++ Java IPC race condition CPU CPU CPU CPU ilovecpp race condition shared_ptr/scoped_ptr 18 50% http://blog.csdn.net/myan/article/details/3144661 Google

28 1 shared_ptr boost::bind shared_ptr weak_ptr shared_ptr boost::shared_ptr http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm C++11 unique_ptr auto_ptr shared_ptr TR1 C++ 19 C++ STL shared_ptr std::vector shared_ptr / 1.14 Observer 1.8 shared_ptr/weak_ptr Observer Observer Observer OO Observer Observer friend Observer Observer class Foo 1 30 work around Base class 19 C++ new delete memory leak C++ smart pointer STL Boost ( ) 4 smart pointers C++ memory leak!

1.14 Observer 29 Observer Java Java 8 Closure C# delegate C++ boost::function/ boost::bind 20 C++ Observer Signal/Slots QT thread safe race condition free thread contention free Signal/Slots shared_ptr 1.8 Observer 2.8 shared_ptr copy-on-write C++11 variadic template trivial template<typename Signature> class SignalTrivial; recipes/thread/signalslottrivial.h // NOT thread safe!!! template <typename RET, typename... ARGS> class SignalTrivial<RET(ARGS...)> public: typedef std::function<void (ARGS...)> Functor; void connect(functor&& func) functors_.push_back(std::forward<functor>(func)); void call(args&&... args) for (const Functor& f: functors_) f(args...); private: std::vector<functor> functors_; ; recipes/thread/signalslottrivial.h Signal/Slots Slot unregister recipes/thread/signalslot.h 20 11.5 boost::function boost::bind function/bind http://blog.csdn.net/myan/article/details/5928531

30 1 C++ Ruminations on C++ Koenig Moo 2003 C++ 6 handle/body idiom C++ shared_ptr C++ auto_ptr C++ shared_ptr C++ 21 2001 STL 10 STL vector 21 http://en.wikipedia.org/wiki/reinventing_the_wheel