
ã¯ããã«
ãã®èšäºã¯äžé£ã®èšäºã®ç¶ãã§ãïŒ
ã·ã³ã°ã«ãã³ãã¿ãŒã³ã®äœ¿çš[1] ã
ã·ã³ã°ã«ãã³ãšãªããžã§ã¯ãã®å¯¿åœ[2] ã
äŸåé¢ä¿ã®åŠçãšèšèšãã¿ãŒã³ã®çæ[3] ã
ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã§ã®
ã·ã³ã°ã«ãã³å®è£
[4] ã æ¬¡ã«ããã«ãã¹ã¬ããã«ã€ããŠèª¬æããŸãã ãã®ãããã¯ã¯èšå€§ã§å€é¢çã§ããããããã¹ãŠãç¶²çŸ
ããããšã¯ã§ããŸããã ããã§ã¯ããã«ãã¹ã¬ããã«ã€ããŠãŸã£ããèããªãããã«ãããããŸãã¯éåžžã«å°ãªãéã§ããã«ã€ããŠèããããšãå¯èœã«ããããã€ãã®å®çšçãªããšã«çŠç¹ãåœãŠãŸãã ããæ£ç¢ºã«ã¯ãèšè𿮵éã§ã®ã¿æ€èšããå®è£
ã§ã¯ãªããšèããŸãã ã€ãŸã é çã®ãªãæ£ããæ§æãèªåçã«åŒã³åºãããããšã確èªããæ¹æ³ã«ã€ããŠã®è³ªåãè°è«ãããŸãã ãã®ã¢ãããŒãã«ãããç«¶åç¶æ
ïŒç«¶åç¶æ
ãç«¶å
ç¶æ
[5]ãåç
§ïŒããã³ãããããã¯ïŒãããããã¯ã
ãããããã¯[6]ãåç
§ïŒã«ãã£ãŠåŒãèµ·ããããåé¡ã倧å¹
ã«æžããããšãã§ããŸãã ãã®äºå®èªäœã¯ããªãã®äŸ¡å€ããããŸãã ãŸããããã¯ãã¢ãããã¯æäœã䜿çšããã«ãè€æ°ã®ã¹ã¬ããããåæã«ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããã¢ãããŒããæ€èšãããŸãïŒ
ã»ãšãã©ã®èšäºã¯ç¹å®ã®ããªããã£ãã»ããã®ã¿ã«éå®ãããŠããã䜿çšã¯äŸ¿å©ã§ããããã«ãã¹ã¬ããç°å¢ã§çºçããäžè¬çãªåé¡ã解決ããããšã¯ã§ããŸããã 以äžã¯ããããã®ã¿ã€ãã®ã¢ãããŒãã§äžè¬çã«äœ¿çšããããªã¹ãã§ãã åæã«ãèªè
ã¯ãã§ã«ãã®ãããªã¢ãããŒãã«ç²ŸéããŠãããšæ³å®ããã®ã§ãããã«çŠç¹ãåãããŸããã
䜿çšãããšã³ãã£ãã£ïŒ
ãã¥ãŒããã¯ã¹ã€ã³ã¿ãŒãã§ã€ã¹ã®èª¬æïŒ
struct Mutex { void lock(); void unlock(); private:
|
RAIIããªããã£ãïŒäŸå€ã«å¯ŸããŠå®å
šïŒïŒ
struct Lock { Lock(Mutex& mutex_) : mutex(mutex_) { mutex.lock(); } ~Lock() { mutex.unlock(); } private: Mutex& mutex; }; |
ç°¡åãªäŸãšããŠã®ãããã®ã¯ã©ã¹ïŒ
struct A { int data; mutable Mutex m; }; |
䜿çšäŸïŒ
äŸ1.ããªããã£ãã¢ãããŒãïŒCã¹ã¿ã€ã«
A a; amlock(); a.data = 10; amunlock(); |
äŸ2.é«åºŠãªã¢ãããŒãïŒRAIIã¹ã¿ã€ã«
A a; { Lock lock(am); a.data = 10; } |
äŸ3.å®éã«çæ³çïŒããã¯ã®ã«ãã»ã«å
struct B { void setData(int data_) { Lock lock(m); data = data_; } int getData() const { Lock lock(m); return data; } private: mutable Mutex m; int data; }; B b; b.setData(10); int x = b.getData(); |
åŸè
ã®ãªãã·ã§ã³ã¯ããã«ãã¹ã¬ããã«é¢ããèšäºã§ã¯ãã£ãã«èŠãããªãããšã¯æ³šç®ã«å€ããŸããããã¯éåžžã«æ²ããäºå®ã§ãã
ãã«ãã¹ã¬ãããäžè¬çãªããŒã¿ãšãã¥ãŒããã¯ã¹[9] ã
ã¯ãã¹ãã©ãããã©ãŒã ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³[10] ã
C ++ã®ã¹ããªãŒã ãããã¯ãæ¡ä»¶å€æ°11 ïŒããŒã2ïŒ[11] ã ãã®èšäºã§ã¯ããã«ãã¹ã¬ããããªããã£ãã®åŠçã倧å¹
ã«ç°¡çŽ åããã®ã«åœ¹ç«ã€è峿·±ãåé¡ã«ã€ããŠèª¬æã
ãŸãïŒC ++ 11ã®ã¹ããªãŒã ãããã¯ãæ¡ä»¶å€æ°ïŒããŒã1ïŒ[12] ã
çžäºæä»ããã¯ãé²ã2ã€ã®ç°¡åãªã«ãŒã«[13]ãåç
§ïŒ ïŒ ããã€ãã®ç¹ã§ããã®èšäºã¯
ãåæå€ã䜿çšããæ£ãããã¥ãŒããã¯ã¹ã®äœ¿çšã®
匷å¶[14]ããåŸãã¢ã€ãã¢ãçºå±ããããã®ã«ãªããŸãã ãã ãã以äžã®ã¢ã€ãã¢ãšå®è£
æ¹æ³ã¯ãèšäºãšã¯ç¬ç«ããŠéçºãããŸããã
äžå€é
å¥åŠãªããšã«ããªããžã§ã¯ãã®äžå€æ¡ä»¶ããã§ãã¯ããããšããããã«ãã¹ã¬ããã®åé¡ã®è°è«ãå§ããŸãã ããã«ãããããããéçºãããäžå€åŒã®ã¡ã«ããºã ã¯å°æ¥äœ¿çšãããŸãã
ãäžå€åŒãã®æŠå¿µã«ç²ŸéããŠããªã人ã®ããã«ããã®ãã©ã°ã©ãã¯æ§ããããŸãã æ®ãã¯å®å
šã«ã¹ãããããŠå®è£
ã«çŽæ¥é²ãããšãã§ããŸãã ãããã£ãŠãOOPã§ã¯ãå¥åŠãªããšã«ããªããžã§ã¯ããæäœããŸãã åãªããžã§ã¯ãã«ã¯ç¬èªã®ç¶æ
ããããé宿°é¢æ°ã«ãã£ãŠåŒã³åºããããšãç¶æ
ãå€ãããŸãã ãããã£ãŠãååãšããŠãåã¯ã©ã¹ã«ã¯ç¹å®ã®äžå€æ¡ä»¶ããããç¶æ
ã®å€åããšã«æºããå¿
èŠããããŸãã ããšãã°ããªããžã§ã¯ããèŠçŽ ã®ã«ãŠã³ã¿ãŒã§ããå Žåãããã°ã©ã ãå®è¡ãããä»»æã®æç¹ã§ããã®ã«ãŠã³ã¿ãŒã®å€ãè² ã§ãã£ãŠã¯ãªããªãããšã¯æããã§ãã ãã®å Žåãäžå€åŒã¯ã«ãŠã³ã¿ãŒã®è² ã§ãªãå€ã§ãã ãããã£ãŠãäžå€åŒã®ä¿åã«ããããªããžã§ã¯ãã®ç¶æ
ãäžè²«ããŠããããšãããçšåºŠä¿èšŒãããŸãã
ã¯ã©ã¹ã«äžå€åŒãä¿åãããŠããå Žåã¯
true
ãè¿ããäžå€åŒãéåãããŠããå Žåã¯
false
ãè¿ã
isValid
ã¡ãœãããããããšãæ³åããŠãã ããã æ¬¡ã®ãéè² ãã«ãŠã³ã¿ãŒãæ€èšããŠãã ããã
struct Counter { Counter() : count(0) {} bool isValid() const { return count >= 0; } int get() const { return count; } void set(int newCount) { count = newCount; } void inc() { ++ count; } void dec() { -- count; } private: int count; };
äœ¿çšæ³ïŒ
Counter c; c.set(5); assert(c.isValid());
ããã§ãå€ã倿Žããããã³ã«
isValid
ã¡ãœãããåŒã³åºããªãããã«ãäžå€åŒã®æ€èšŒãäœããã®æ¹æ³ã§èªååããããšæããŸãã ãããè¡ãæçœãªæ¹æ³ã¯ããã®åŒã³åºãã
set
ã¡ãœããã«å«ããããšã§ãã ãã ãã倿°ã®é宿°ã¯ã©ã¹ã¡ãœãããååšããå Žåããã®ãããªåã¡ãœããå
ã«ãã®ãã§ãã¯ãæ¿å
¥ããå¿
èŠããããŸãã ããããç§ã¯ããå°ãªãèšè¿°ãšããå€ããåŸãããã«èªååãéæããããšæããŸãã ããã§ã¯å§ããŸãããã
ããã§ã¯ã以åã®äžé£ã®èšäºã§éçºãããããŒã«ã䜿çšããŸãïŒ
ã·ã³ã°ã«ãã³ãã¿ãŒã³ã®äœ¿çš[1] ã
ã·ã³ã°ã«ãã³ãšãªããžã§ã¯ãã®å¯¿åœ[2] ã
äŸåé¢ä¿ã®åŠçãšèšèšãã¿ãŒã³ã®çæ[3] ã
ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã§ã®
ã·ã³ã°ã«ãã³å®è£
[4] ã 以äžã§ã¯ãåç
§ã®ããã«ãã¢ãªã³ã°ãè¡ãå®è£
ã瀺ããŸãã
An.hpp #ifndef AN_HPP #define AN_HPP #include <memory> #include <stdexcept> #include <string> // , . [1] #define PROTO_IFACE(D_iface, D_an) \ template<> void anFill<D_iface>(An<D_iface>& D_an) #define DECLARE_IMPL(D_iface) \ PROTO_IFACE(D_iface, a); #define BIND_TO_IMPL(D_iface, D_impl) \ PROTO_IFACE(D_iface, a) { a.create<D_impl>(); } #define BIND_TO_SELF(D_impl) \ BIND_TO_IMPL(D_impl, D_impl) // , DIP - dependency inversion principle template<typename T> struct An { template<typename U> friend struct An; An() {} template<typename U> explicit An(const An<U>& a) : data(a.data) {} template<typename U> explicit An(An<U>&& a) : data(std::move(a.data)) {} T* operator->() { return get0(); } const T* operator->() const { return get0(); } bool isEmpty() const { return !data; } void clear() { data.reset(); } void init() { if (!data) reinit(); } void reinit() { anFill(*this); } T& create() { return create<T>(); } template<typename U> U& create() { U* u = new U; data.reset(u); return *u; } private: // // // anFill, // // T T* get0() const { // const_cast<An*>(this)->init(); return data.get(); } std::shared_ptr<T> data; }; // , . [1] // // , // , // . . [3] template<typename T> void anFill(An<T>& a) { throw std::runtime_error(std::string("Cannot find implementation for interface: ") + typeid(T).name()); } #endif
äžè²«æ§ã確èªã§ããããã«ããããã«ã次ã®ããã«ãªããžã§ã¯ããžã®ã¢ã¯ã»ã¹ã倿ŽããŸãïŒãã©ã€ããŒãã¡ãœãã
get0
ïŒã
template<typename T> struct An {
ãã¹ãŠé 調ã§ããæ€èšŒãé²è¡äžã§ãã ãããåé¡ã¯ã倿ŽåŸã§ã¯ãªãã倿Žåã«çºçããããšã§ãã ãããã£ãŠããªããžã§ã¯ãã¯äžè²«æ§ã®ãªãç¶æ
ã«ãªãå¯èœæ§ããããæ¬¡ã®åŒã³åºãã®ã¿ããã®ãžã§ããå®è¡ããŸãã
c->set(2); c->set(-2);
ãã§ãã¯ã¯ã倿Žåã§ã¯ãªã倿ŽåŸã«è¡ãããã«ããŸãã ãããè¡ãã«ã¯ãå¿
èŠãªæ€èšŒãè¡ããããã¹ãã©ã¯ã¿ã§ãããã·ãªããžã§ã¯ãã䜿çšããŸãã
template<typename T> struct An {
äœ¿çšæ³ïŒ
An<Counter> c; c->set(2); c->set(-2);
å¿
èŠã§ããã
ã¹ããŒããã¥ãŒããã¯ã¹
次ã«ããã«ãã¹ã¬ããã¿ã¹ã¯ã«ç®ãåããŸãã mutexã®æ°ããå®è£
ãäœæããã¹ããŒããã€ã³ã¿ãŒãšã®é¡æšã«ãã£ãŠãã¹ããŒãããšåŒã³ãŸãã å·§åŠãªmutextã®ã¢ã€ãã¢ã¯ããªããžã§ã¯ããæäœãããã¹ãŠã®ãæ±ããäœæ¥ãåŒãåããããšã§ãããç§ãã¡ã«ã¯æãããããéšåããããŸãã
ãããæºåããã«ã¯ããéåžžã®ããã¥ãŒããã¯ã¹ãå¿
èŠã§ãïŒã¹ããŒããã€ã³ã¿ãŒã®ããã«ãéåžžã®ãã€ã³ã¿ãŒãå¿
èŠã§ãïŒã
ããã§ã以åã«äžå€åŒããã§ãã¯ããéã«äœ¿çšãããã©ã¯ãã£ã¹ãæ¹åããŸãã ãããè¡ãã«ã¯ããããã·ã¯ã©ã¹ãã¹ãã©ã¯ã¿ã ãã§ãªããã³ã³ã¹ãã©ã¯ã¿ã䜿çšããŸãã
template<typename T> struct AnLock {
äœ¿çšæ³ïŒ
AnLock<Counter> c; c->set(2);
宿°ãªã³ã¯ã䜿çšããŠããå Žåãå€ã倿Žãããšã³ã³ãã€ã«ãšã©ãŒãçºçããããšã«æ³šæããŠãã ããïŒ
shared_ptr
çŽæ¥äœ¿çšããã®ã§ã¯ãªãïŒã
const AnLock<Counter>& cc = c; cc->set(3);
ç§ãã¡ãåŸããã®ãæ€èšããŠãã ããã
Counter
ããã³
Mutex
ã®ã¡ãœããã®ç»é¢åºåã远å ãããšãå€ã倿Žããããšãã«æ¬¡ã®ç»é¢åºåãåŸãããŸãã
ãã¥ãŒããã¯ã¹::ããã¯
ã«ãŠã³ã¿ãŒ::ã»ããïŒ2
ãã¥ãŒããã¯ã¹::ããã¯è§£é€
ç»é¢ã«è¡šç€ºãããšãã®ã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ïŒ
ãã¥ãŒããã¯ã¹::ããã¯
ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
ãã¥ãŒããã¯ã¹::ããã¯è§£é€
å©äŸ¿æ§ã¯æçœã§ãããã¥ãŒããã¯ã¹ãæç€ºçã«åŒã³åºãã®ã§ã¯ãªãããã¥ãŒããã¯ã¹ãååšããªããã®ããã«ãªããžã§ã¯ããæäœããã ãã§ãå
éšã§å¿
èŠãªãã¹ãŠãçºçããŸãã
ããšãã°ã
inc
2ååŒã³åºããŠã¢ãããã¯ã«å®è¡ããå¿
èŠãããå Žåã¯ã©ãããã°ããã§ããããã åé¡ãããŸããïŒ æåã«ã䟿å®äžã
AnLock
ã¯ã©ã¹ã«
typedef
ãããã€ã远å ã
typedef
ã
template<typename T> struct AnLock {
ãããŠãæ¬¡ã®æ§æã䜿çšããŸãã
{ AnLock<Counter>::WAccess a = c; a->inc(); a->inc(); }
ããã«ãããæ¬¡ã®çµè«ãåŸãããŸãã
ãã¥ãŒããã¯ã¹::ããã¯
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ1
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ2
ãã¥ãŒããã¯ã¹::ããã¯è§£é€
ãã©ã³ã¶ã¯ã·ã§ã³ã®ãããªãã®ã§ãããïŒ
ã¹ããŒãRWãã¥ãŒããã¯ã¹
ãã®ãããä»åºŠã¯ãèªã¿åã/æžã蟌ã¿ãã¥ãŒããã¯ã¹ãšåŒã°ããå°ãè€éãªæ§é ã®å®è£
ã詊ã¿ãããšãã§ããŸãïŒ
ãªãŒããŒ-ã©ã€ã¿ãŒããã¯[7]ãåç
§ïŒã 䜿çšã®æ¬è³ªã¯éåžžã«ç°¡åã§ããè€æ°ã®ã¹ããªãŒã ãããªããžã§ã¯ãããŒã¿ãèªã¿åãæ©èœãèš±å¯ããåæã«èªã¿åããšæžã蟌ã¿ãŸãã¯æžã蟌ã¿ãšæžã蟌ã¿ãåæã«çŠæ¢ããå¿
èŠããããŸãã
ãã®ã€ã³ã¿ãŒãã§ã€ã¹ãåãã
RWMutex
å®è£
ããã§ã«ãããšä»®å®ããŸãã
è¡ãå¿
èŠãããã®ã¯ãå®è£
ããããã«å€æŽããŠããããã·ã¿ã€ã
RAccess
ãš
WAccess
ãç°ãªã颿°ã䜿çšããããã«ããããšã ãã§ããããã«æãããŸãã
template<typename T> struct AnRWLock {
äœ¿çšæ³ïŒ
AnRWLock<Counter> c; c->set(2);
çµæïŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::ã»ããïŒ2
RWMutex :: wunlock
ãããŸã§ã®ãšããè¯ãïŒ ããããæ¬¡ã®ã³ãŒãïŒ
std::cout << "Extracted value: " << c->get() << std::endl;
ããã¯äžããïŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
RWMutex :: wunlock
äžéšã®äººã«ãšã£ãŠã¯ãããã¯é©ãããšã§ã¯ãããŸããããæ®ãã«ã€ããŠã¯ããªãæåŸ
ã©ããã«æ©èœããªãã®ãã説æããŸãã çµå±ã宿°ã¡ãœããã䜿çšãããããçè«çã«ã¯å®æ°ã¡ãœãã
operator->
ã䜿çšããå¿
èŠããããŸããã ããããã³ã³ãã€ã©ã¯ããã¯æããŸããã ããã¯ãæäœãé çªã«é©çšããããšããäºå®ã«ãããã®ã§ããæåã«ãæäœ
->
ãé宿°ãªããžã§ã¯ãã«é©çšãããæ¬¡ã«å®æ°ã¡ãœãã
Counter::get
ãåŒã³åºãããŸãããåè»ã¯æ®ããŸãã é宿°
operator->
ã¯ãã§ã«åŒã³åºãããŠããŸãã
ç°¡åãªè§£æ±ºçãšããŠããªããžã§ã¯ãã«ã¢ã¯ã»ã¹ããåã«å®æ°ã«ãã£ã¹ããããªãã·ã§ã³ãææ¡ã§ããŸãã
const AnRWLock<Counter>& cc = c; std::cout << "Extracted value: " << cc->get() << std::endl;
çµæïŒ
RWMutex :: rlock
ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
RWMutex ::ã©ã³ããã¯
ãããããã®ãœãªã¥ãŒã·ã§ã³ã¯ãæ§ããã«èšã£ãŠããããŸãé
åçã§ã¯ãããŸããã åçŽãã€ç°¡æœã«èšè¿°ãã宿°ã¡ãœãããåŒã³åºããã³ã«ããã°ãæ§é ã䜿çšããããªãã
ãã®åé¡ã解決ããããã«ãæ°ããæŒç®åãé·ãç¢å°
--->
ãå°å
¥ã
--->
ãããã¯ãªããžã§ã¯ãã«æžã蟌ã¿ãŸãã é宿°ã¡ãœããã«ã¢ã¯ã»ã¹ããéåžžã®ïŒçãïŒç¢å°
->
ããã®ãŸãŸã«ããŠãããŸãã èªã¿åãã«çãç¢å°ã䜿çšããæžã蟌ã¿ã«é·ãç¢å°ã䜿çšããçç±ã¯æ¬¡ã®ãšããã§ãã
- ããžã¥ã¢ã« ã©ã®æäœã䜿çšãããŠããããããã«ç¢ºèªã§ããŸãã
- ã»ãã³ãã£ã㯠ã èªæžã¯ããªããžã§ã¯ãã®äžçš®ã®è¡šé¢çãªäœ¿çšã§ãïŒè§Šããããè§£æŸãããŸãã èšé²ã¯ãå
éšã®ããæ·±ãæäœãããã°å€åã§ãããããã£ãŠãç¢å°ã¯ããé·ããªããŸãã
- å®çšç ã éåžžã®ãã¥ãŒããã¯ã¹ãRWãã¥ãŒããã¯ã¹ã«çœ®ãæããå Žåããããã®å Žæã§çãç¢å°ãé·ãç¢å°ã«çœ®ãæããã ãã§ã³ã³ãã€ã«ãšã©ãŒãä¿®æ£ããå¿
èŠãããããã¹ãŠãæé©ãªæ¹æ³ã§æ©èœããŸãã
ããã§ããããããç±å¿ãªèªè
ã¯è³ªåãããŸããïŒèšäºã®èè
ãšåãéèãã©ãã§æã«å
¥ãããïŒ ãã£ã±ã

å®è£
ãèŠãŠã¿ãŸãããïŒ
äœ¿çšæ³ïŒ
AnRWLock<Counter> c;
ã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ïŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::ã»ããïŒ2
RWMutex :: wunlock
é·ãç¢å°ã䜿çšããããšãé€ããŠããã¹ãŠã以åãšåãã§ãã ããã«èª¿æ»ããŸãã
std::cout << "Extracted value: " << c->get() << std::endl;
RWMutex :: rlock
ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
RWMutex ::ã©ã³ããã¯
ç§ã®æèŠã§ã¯ãæžãèŸŒã¿æäœã«é·ãç¢å°ã䜿çšããããšã¯æ£åœåãããŸããããã¯ç§ãã¡ã®åé¡ãéåžžã«ãšã¬ã¬ã³ããªæ¹æ³ã§è§£æ±ºããŸãã
èªè
ããã®ä»çµã¿ãããçè§£ããŠããªãå Žåèªè
ããããã©ã®ããã«æ©èœããããããçè§£ããŠããªãå Žåã¯ããé·ããç¢å°ããã³ããšããŠäœ¿çšããããã®æ¬¡ã®åçã®ã³ãŒããæäŸããŸãã
(c--)->set(2);
ã³ããŒãªã³ã©ã€ã
次ã«ã次ã®è峿·±ãæçšãªã€ãã£ãªã ã
ã³ããŒãªã³ã©ã€ã ïŒ
COW ïŒããŸãã¯
ã³ããŒãªã³ã©ã€ã[8]ãèããŠ
ãã ãã ã ååã瀺ãããã«ãäž»ãªèãæ¹ã¯ããªããžã§ã¯ãã®ããŒã¿ã倿ŽããçŽåã«ãæ°ããã¡ã¢ãªäœçœ®ãžã®ã³ããŒãæåã«çºçããæ¬¡ã«ããŒã¿ãæ°ããã¢ãã¬ã¹ã«å€æŽããããšããããšã§ãã
COWã¢ãããŒãã¯ãã«ãã¹ã¬ããã«çŽæ¥é¢é£ããŠããŸããããããã§ããã®ã¢ãããŒããä»ã®ã¢ãããŒããšçµã¿åãããŠäœ¿çšââãããšã䜿ããããã倧å¹
ã«åäžããå€ãã®ããããã®ãªãèŠçŽ ã远å ãããŸãã ãã®ããã
COWã®å®è£
ã以äžã«ç€ºããŸãã ããã«ãéçºãããããªãã¯ã¯ããã®ã€ãã£ãªã ã®å®è£
ã«ç°¡åãã€èªç¶ã«ç§»è¡ãããŸãã
ãã®ãããRWãã¥ãŒããã¯ã¹ãšåæ§ã«ãèªã¿åãæäœãšæžãèŸŒã¿æäœãåºå¥ããå¿
èŠããããŸãã èªã¿åãæã«ã¯ç¹å¥ãªããšã¯çºçããŸããããæžãèŸŒã¿æã«ã¯ããªããžã§ã¯ãã«è€æ°ã®ææè
ãããå ŽåããŸããã®ãªããžã§ã¯ããã³ããŒããå¿
èŠããããŸãã
template<typename T> struct AnCow {
ããªã¢ãŒãã£ãã¯ãªããžã§ã¯ãã®äœ¿çšã¯ããã§ã¯èæ
®ãããªãïŒã€ãŸãããã³ãã¬ãŒãã¯ã©ã¹
T
ç¶æ¿ãäœæããªãïŒããšã«æ³šæãã䟡å€ããããŸãã ããã¯ãã®èšäºã®ç¯å²ãè¶
ããŠããŸãã æ¬¡åã®èšäºã§ã¯ããã®åé¡ã®è©³çްãªè§£æ±ºçã説æããŸãããå®è£
ã¯éåžžã«ãŸãã§ãã
䜿çšã«ç§»ããŸãããïŒ
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
AnCow<Counter> c; c--->set(2); | ã«ãŠã³ã¿ãŒ::ã»ããïŒ2
|
std::cout << "Extracted value: " << c->get() << std::endl; | ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
|
AnCow<Counter> d = c; std::cout << "Extracted value: " << d->get() << std::endl; | ã«ãŠã³ã¿ãŒ::ååŸïŒ2
æœåºå€ïŒ2
|
d--->inc(); | ã«ãŠã³ã¿ãŒã³ããŒã¢ã¯ã¿ãŒïŒ2
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ3
|
c--->dec(); | ã«ãŠã³ã¿ãŒ:: decïŒ1
|
æåã¯ãè峿·±ãããšã¯äœãèµ·ãããŸãããå€ãèšå®ããç»é¢ã«åãå€ã衚瀺ããã®ã¯
2
ã§ãã æ¬¡ã«ãå€ã¯æ°ãã倿°ã«å²ãåœãŠãããŸããããªããžã§ã¯ãããŒã¿ã¯åãããã«äœ¿çšãããŸãã å€
d->get()
åºåãããšããåããªããžã§ã¯ãã䜿çšãããŸãã
次ã«ã
d--->inc()
ãåŒã³åºããããšãæãè峿·±ãããšãèµ·ãããŸããæåã«ãªããžã§ã¯ããã³ããŒãããæ¬¡ã«çµæã®å€ã3ã«å¢å ããŸãã æ¬¡ã®
c--->dec()
åŒã³åºãã¯ã³ããŒãããŸããã ææè
ã¯1人ã«ãªãããªããžã§ã¯ãã®2ã€ã®ç°ãªãã³ããŒããããŸãã ãã®äŸã¯ã
COWã®ä»äºãæç¢ºã«ç€ºããŠãããšæããŸãã
ã¡ã¢ãªå
ã®ããŒå€ã¹ãã¬ãŒãž
æåŸã«ãéçºãããææ³ã䜿çšããŠãã«ãã¹ã¬ããç°å¢ã§äœæ¥ããå Žåãã¡ã¢ãªå
ã®ããŒå€ã¹ãã¬ãŒãžã®å®è£
ã®ããã€ãã®ããªãšãŒã·ã§ã³ãæ€èšããŸãã
ãªããžããªã«ã¯æ¬¡ã®å®è£
ã䜿çšããŸãã
template<typename T_key, typename T_value> struct KeyValueStorageImpl {
ã¹ãã¬ãŒãžãã·ã³ã°ã«ãã³ã«ãã€ã³ãããŠãããã«æäœãç°¡çŽ åããŸãïŒ
ã·ã³ã°ã«ãã³ãã¿ãŒã³ã®äœ¿çš[1]ãåç
§ïŒã
template<typename T_key, typename T_value> void anFill(AnRWLock<KeyValueStorageImpl<T_key, T_value>>& D_an) { D_an = anSingleRWLock<KeyValueStorageImpl<T_key, T_value>>(); }
ãããã£ãŠã
AnRWLock<KeyValueStorageImpl<T,V>>
ã€ã³ã¹ã¿ã³ã¹ãäœæãããšãã·ã³ã°ã«ãã³ããæœåºããããªããžã§ã¯ãããæ³šããããŸãã
AnRWLock<KeyValueStorageImpl<T,V>>
ã¯åžžã«åäžã®ã€ã³ã¹ã¿ã³ã¹ãæããŸãã
åèã®ããã«ã䜿çšããã€ã³ãã©ã¹ãã©ã¯ãã£ã瀺ããŸãã
AnRWLock.hpp #ifndef AN_RWLOCK_HPP #define AN_RWLOCK_HPP #include <memory> #include <stdexcept> #include <string> #include "Mutex.hpp" // fill #define PROTO_IFACE_RWLOCK(D_iface, D_an) \ template<> void anFill<D_iface>(AnRWLock<D_iface>& D_an) #define DECLARE_IMPL_RWLOCK(D_iface) \ PROTO_IFACE_RWLOCK(D_iface, a); #define BIND_TO_IMPL_RWLOCK(D_iface, D_impl) \ PROTO_IFACE_RWLOCK(D_iface, a) { a.create<D_impl>(); } #define BIND_TO_SELF_RWLOCK(D_impl) \ BIND_TO_IMPL_RWLOCK(D_impl, D_impl) #define BIND_TO_IMPL_SINGLE_RWLOCK(D_iface, D_impl) \ PROTO_IFACE_RWLOCK(D_iface, a) { a = anSingleRWLock<D_impl>(); } #define BIND_TO_SELF_SINGLE_RWLOCK(D_impl) \ BIND_TO_IMPL_SINGLE_RWLOCK(D_impl, D_impl) template<typename T> struct AnRWLock { template<typename U> friend struct AnRWLock; struct RAccess { RAccess(const AnRWLock& ref_) : ref(ref_) { ref.mutex->rlock(); } ~RAccess() { ref.mutex->runlock(); } const T* operator->() const { return ref.get0(); } private: const AnRWLock& ref; }; struct WAccess { WAccess(const AnRWLock& ref_) : ref(ref_) { ref.mutex->wlock(); } ~WAccess() { ref.mutex->wunlock(); } T* operator->() const { return ref.get0(); } private: const AnRWLock& ref; }; AnRWLock() {} template<typename U> explicit AnRWLock(const AnRWLock<U>& a) : data(a.data) {} template<typename U> explicit AnRWLock(AnRWLock<U>&& a) : data(std::move(a.data)) {} WAccess operator--(int) { return *this; } RAccess operator->() const { return *this; } bool isEmpty() const { return !data; } void clear() { data.reset(); } void init() { if (!data) reinit(); } void reinit() { anFill(*this); } T& create() { return create<T>(); } template<typename U> U& create() { U* u = new U; data.reset(u); mutex.reset(new RWMutex); return *u; } private: T* get0() const { const_cast<AnRWLock*>(this)->init(); return data.get(); } std::shared_ptr<T> data; std::shared_ptr<RWMutex> mutex; }; template<typename T> void anFill(AnRWLock<T>& a) { throw std::runtime_error(std::string("Cannot find implementation for interface: ") + typeid(T).name()); } template<typename T> struct AnRWLockAutoCreate : AnRWLock<T> { AnRWLockAutoCreate() { this->create(); } }; template<typename T> AnRWLock<T> anSingleRWLock() { return single<AnRWLockAutoCreate<T>>(); } #endif
AnCow.hpp #ifndef AN_COW_HPP #define AN_COW_HPP #include <memory> #include <stdexcept> #include <string> // fill #define PROTO_IFACE_COW(D_iface, D_an) \ template<> void anFill<D_iface>(AnCow<D_iface>& D_an) #define DECLARE_IMPL_COW(D_iface) \ PROTO_IFACE_COW(D_iface, a); #define BIND_TO_IMPL_COW(D_iface, D_impl) \ PROTO_IFACE_COW(D_iface, a) { a.create<D_impl>(); } #define BIND_TO_SELF_COW(D_impl) \ BIND_TO_IMPL_COW(D_impl, D_impl) #define BIND_TO_IMPL_SINGLE_COW(D_iface, D_impl) \ PROTO_IFACE_COW(D_iface, a) { a = anSingleCow<D_impl>(); } #define BIND_TO_SELF_SINGLE_COW(D_impl) \ BIND_TO_IMPL_SINGLE_COW(D_impl, D_impl) template<typename T> struct AnCow { template<typename U> friend struct AnCow; AnCow() {} template<typename U> explicit AnCow(const AnCow<U>& a) : data(a.data) {} template<typename U> explicit AnCow(AnCow<U>&& a) : data(std::move(a.data)) {} T* operator--(int) { return getW0(); } const T* operator->() const { return getR0(); } bool isEmpty() const { return !data; } void clear() { data.reset(); } void init() { if (!data) reinit(); } void reinit() { anFill(*this); } T& create() { return create<T>(); } template<typename U> U& create() { U* u = new U; data.reset(u); return *u; } // TODO: update clone functionality on creating derived instances void clone() { data.reset(new T(*data)); } private: T* getR0() const { const_cast<AnCow*>(this)->init(); return data.get(); } T* getW0() { init(); if (!data.unique()) clone(); return data.get(); } std::shared_ptr<T> data; }; template<typename T> void anFill(AnCow<T>& a) { throw std::runtime_error(std::string("Cannot find implementation for interface: ") + typeid(T).name()); } template<typename T> struct AnCowAutoCreate : AnCow<T> { AnCowAutoCreate() { this->create(); } }; template<typename T> AnCow<T> anSingleCow() { return single<AnCowAutoCreate<T>>(); } #endif
次ã«ãåçŽãªãã®ããè€éãªãã®ãŸã§ããã®ãªããžããªã䜿çšããããŸããŸãªæ¹æ³ãæ€èšããŸãã
äŸ1.æãåçŽãªäœ¿çšã
远å ã®é£Ÿããªãã§ã¹ãã¬ãŒãžãçŽæ¥äœ¿çšããŸãã
䜿çšäŸïŒ
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
| RWMutex :: wlock
Key-ValueïŒããŒã®æ¿å
¥ïŒPeter
RWMutex :: wunlock
|
kv--->set("Nick", 25); | RWMutex :: wlock
Key-ValueïŒããŒãæ¿å
¥ïŒNick
RWMutex :: wunlock
|
std::cout << "Peter age: " << kv->get("Peter") << std::endl; | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒPeter
ããŒã¿ãŒå¹Žéœ¢ïŒ28
RWMutex ::ã©ã³ããã¯
|
æåã®è¡ã§ã¯ãã·ã³ã°ã«ãã³ã䜿çšããŠãªããžããªã®åäžã€ã³ã¹ã¿ã³ã¹ã泚ããã
kv
ãªããžã§ã¯ããäœæããŸãïŒ
anFill
颿°ãåç
§ïŒã 次ã«ãPeterãšNickã远å ãããPeterã®å¹Žéœ¢ã衚瀺ãããŸãã
åºåãããæžãèŸŒã¿æã«æžã蟌ã¿ããã¯ãèªåçã«ååŸãããèªã¿åãæã«èªã¿åãããã¯ãååŸãããããšãæããã ãšæããŸãã
äŸ2.ãã¹ããããRWãã¥ãŒããã¯ã¹ã
ããå°ãè€éãªäŸãèããŠã¿ãŸãããã
ååä»ãã«ãŠã³ã¿ãŒãååŸCounter
ããè€æ°ã®ã¹ã¬ãããã䜿ââçšããããšããŸããåé¡ãããŸããïŒ
䜿çšäŸïŒ
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
KVRWType kv; | RWMutex :: wlock
Key-ValueïŒããŒã®æ¿å
¥ïŒãŠãŒã¶ãŒ
RWMutex :: wunlock
|
kv--->set("sessions", AnRWLockAutoCreate<Counter>()); | RWMutex :: wlock
Key-ValueïŒããŒã®æ¿å
¥ïŒã»ãã·ã§ã³
RWMutex :: wunlock
|
kv->get("users")--->inc(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ1
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
kv->get("sessions")--->inc(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒã»ãã·ã§ã³
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ1
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
kv->get("sessions")--->dec(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒã»ãã·ã§ã³
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ:: decïŒ0
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
圌ããèšãããã«ãåºæ¥äžããïŒäŸ3.ã¢ã¯ã»ã¹ã®æé©åã
次ã®èšäºã§ããã€ãã®æé©åã«ã€ããŠã話ããããšæããŸãããç§ã¯ããã§ãéåžžã«éèŠãªæé©åã«ã€ããŠèª¬æããŸãã以äžã¯ãæ¯èŒã®ããã®ããŸããŸãªäœ¿çšäŸã§ãããªãã·ã§ã³1ïŒéåžž
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
kv->get("users")--->inc(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ2
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
ãªãã·ã§ã³2ïŒæé©
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
auto users = kv->get("users"); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
RWMutex ::ã©ã³ããã¯
|
users--->inc(); | RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ3
RWMutex :: wunlock
|
2çªç®ã®äŸã¯ããªããžã§ã¯ãã®2çªç®ã®æžã蟌ã¿ãã¥ãŒããã¯ã¹ãCounter
ãããŒå€ã¹ãã¬ãŒãžãå¶åŸ¡ããæåã®ãã¥ãŒããã¯ã¹ããªãªãŒã¹ããåŸã«ã®ã¿ååŸãããããšã瀺ããŠããŸãããã®å®è£
ã¯ãã¥ãŒããã¯ã¹ã®ããæé©ãªäœ¿çšãæäŸããŸãããçµæãšããŠããé·ãã¬ã³ãŒããååŸããŸãããã¹ãããããã¥ãŒããã¯ã¹ã䜿çšããå Žåã¯ããã®æé©åã«çæããå¿
èŠããããŸããäŸ4.ã¢ãããã¯ãªå€æŽã®ãµããŒãã
ããšãã°ããusersããªã©ã®ã«ãŠã³ã¿ãŒã®1ã€ãã¢ãããã¯ã«100å¢ããå¿
èŠããããšããŸãããã¡ããããã®ããã«ãªãã¬ãŒã·ã§ã³ã100ååŒã³åºãããšãã§ããŸãinc()
ããŸãã¯ããããè¡ãããšãã§ããŸããã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
auto c = kv->get("users"); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
RWMutex ::ã©ã³ããã¯
|
KVRWType::ValueType::WAccess cw = c; cw->set(cw->get() + 100); | RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::ååŸïŒ4
ã«ãŠã³ã¿ãŒ::ã»ããïŒ104
RWMutex :: wunlock
|
WAccess
ããã«äœ¿çšããå Žåããã¹ãŠã®æäœã¯éåžžã®ãçããç¢å°ã§é²ãããšã«æ³šæããŠãã ããããã§ã«ååŸãããªããžã§ã¯ããžã®æžã蟌ã¿ã¢ã¯ã»ã¹ããŸããæäœãšããäºå®ã«æ³šæãæãget
ãšset
ãç§ãã¡ãéæãããã£ããã®ã§ãåããã¥ãŒããã¯ã¹ãäžã«ãããŸããããã¯ããªããžã§ã¯ããæäœãããšãã«ãã©ã³ã¶ã¯ã·ã§ã³ãéãããã«èŠãããšããäºå®ã«éåžžã«äŒŒãŠããŸããäžèšã®æé©åãšåãããªãã¯ã䜿çšããŠãã«ãŠã³ã¿ãŒã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãããªãã·ã§ã³1ïŒéåžž
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
kv->get("users")--->inc(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ4
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
kv->get("sessions")--->dec(); | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒã»ãã·ã§ã³
RWMutex :: wlock
ã«ãŠã³ã¿ãŒ:: decïŒ-1
RWMutex :: wunlock
RWMutex ::ã©ã³ããã¯
|
ãªãã·ã§ã³2ïŒæé©
ã³ãŒã | ã³ã³ãœãŒã«åºå |
---|
AnRWLock<Counter> c1, c2; { KVRWType::RAccess r = kv; c1 = r->get("users"); c2 = r->get("sessions"); } | RWMutex :: rlock
Key-ValueïŒããŒã®æœåºïŒãŠãŒã¶ãŒ
Key-ValueïŒããŒã®æœåºïŒã»ãã·ã§ã³
RWMutex ::ã©ã³ããã¯
|
c1--->inc(); | RWMutex :: wlock
ã«ãŠã³ã¿ãŒ::æ ªåŒäŒç€ŸïŒ5
RWMutex :: wunlock
|
c2--->dec(); | RWMutex :: wlock
ã«ãŠã³ã¿ãŒ:: decïŒ-2
RWMutex :: wunlock
|
ç¹°ãè¿ããŸããã2çªç®ã®äŸã§ã¯ããã¥ãŒããã¯ã¹ãããæé©ã«äœ¿çšãããŸããèªã¿åãããã¯ã¯1åã ãååŸãããæžã蟌ã¿ããã¯ã¯èªã¿åãããã¯ããè§£é€ããããããç«¶åã¢ã¯ã»ã¹ã®ããã©ãŒãã³ã¹ãåäžããŸããäŸ5.çã
æ¬¡ã®æ
å ±ãæã€åŸæ¥å¡ããããšããŸãã struct User { std::string name; int age; double salary;
ç§ãã¡ã®ã¿ã¹ã¯ïŒããšãã°ããã©ã³ã¹ã·ãŒããèšç®ããããã«ãéžæãããŠãŒã¶ãŒã«å¯ŸããŠããŸããŸãªæäœãå®è¡ããŸããæäœãé·ããããç¶æ³ã¯è€éã§ããåæã«ãèšç®ââæã«åŸæ¥å¡ã«é¢ããæ
å ±ã倿Žããããšã¯åãå
¥ããããŸãããç°ãªãææšã¯äžè²«ããŠããå¿
èŠããããããŒã¿ã倿Žãããå Žåããã©ã³ã¹ãåæããªãå¯èœæ§ããããŸããåæã«ãé·æéã®æäœã®çµäºãåŸ
ããã«ãæäœäžã«åŸæ¥å¡ã«é¢ããæ
å ±ã倿ŽããããšæããŸããèšç®ãå®è£
ããã«ã¯ãããæç¹ã®ããŒã¿ã®ã¹ãããã·ã§ãããååŸããå¿
èŠããããŸãããã¡ãããããŒã¿ã¯ç¡é¢ä¿ã«ãªããŸããããã©ã³ã¹ãä¿ã€ããã«ã¯ãäžè²«ããçµæãåŸãããšãããéèŠã§ãããããCOWã䜿çšããŠå®è£
ããæ¹æ³ãèŠãŠã¿ãŸããããæºåæ®µéïŒã€ã³ã¹ã¿ã³ã¹ã®äœææã«COWã䜿çšããUser
BIND_TO_SELF_COW(User) |
ãªããžã§ã¯ããæ ŒçŽã§ããæ°ããã¯ã©ã¹ã宣èšããŸã AnCow
template<typename T_key, typename T_value> struct KeyValueStorageCow : AnRWLock<KeyValueStorageImpl<T_key, AnCow<T_value>>> { }; |
ãªããžããªã®å®£èšïŒint -ãŠãŒã¶ãŒIDãUser -ãŠãŒã¶ãŒ
KeyValueStorageCow<int, User> kv; |
PeterãŠãŒã¶ãŒæ
å ±ã®è¿œå
AnCow<User> u; u--->name = "Peter"; u--->age = 35; u--->salary = 12345; kv--->set(1, u); |
GeorgeãŠãŒã¶ãŒæ
å ±ã®è¿œå
AnCow<User> u; u--->name = "George"; u--->age = 31; u--->salary = 54321; kv--->set(2, u); |
åŸæ¥å¡ã®å¹Žéœ¢æ
å ±ã倿Žãã
AnCow<User> u = kv->get(2); ++ u--->age; kv--->set(2, u); |
ãã©ã³ã¹ä¿æïŒé©åãªãŠãŒã¶ãŒãç²åŸãã
AnCow<User> u1 = kv->get(1); AnCow<User> u2 = kv->get(2); |
å¿
èŠãªãã©ã¡ãŒã¿ãŒã®èšç®ããã¹ãŠã®ããŒã¿ã¯äžè²«æ§ããããæäœãçµäºãããŸã§å€æŽãããŸããã
double totalSalary = u1->salary + u2->salary; double averageSalary = totalSalary/2.; double averageAge = (u1->age + u2->age)/2.; double averageSalaryPerAge = (u1->salary/u1->age + u2->salary/u2->age)/2.; |
ãããã£ãŠãé·æéã®æäœäžããŠãŒã¶ãŒã«é¢ããæ
å ±ã¯æœåºæã«èšé²ãããŸããåç¬éã«ãåŸæ¥å¡ã«é¢ããæ
å ±ã倿Žããããšã¯å¯èœã§ãããããã¯çŸåšã®èšç®ã«ã¯åœ±é¿ããŸããããããŠã次ã®ãã©ã³ã¹ã·ãŒãã§ã¯ãææ°ã®ããŒã¿ã䜿çšãããŸãããã®ã¢ãããŒãã«ãããé·æéã®èšç®ã®çµäºãåŸ
ããã«ããã€ã§ãããŒã¿ã倿Žã§ããå¯èœæ§ãããèšç®ã®èªå·±æŽåæ§ãä¿èšŒãããŸããäžè¬çã«ãèšç®ããåã«ãã¹ãŠã®èŠçŽ ãã³ããŒããããšã¯ãã¡ããå¯èœã§ãããã ããååãªéã®æ
å ±ãããå Žåãããã¯ããªãé·ãæäœã«ãªããŸãããããã£ãŠã瀺ãããã¢ãããŒãã§ã¯ãããŒã¿ã®ã³ããŒãæ¬åœã«å¿
èŠã«ãªããŸã§å»¶æãããŸããèšç®ãšå€æŽã§åæã«äœ¿çšããå Žåã®ã¿ãåæãšåæ
äŸã®åæã以äžã«ç€ºããŸããæãè峿·±ãã®ã¯ããŸããCOWã®æåŸã®äŸã§ããäºæããªãé©ããããã«é ãããŠããŸãã詳现詳现
æåŸã®äŸã®äžé£ã®æäœãæ€èšããŠãã ããã以äžã¯ãã³ã³ããããå€ãååŸããããã®äžè¬çãªæŠèŠã§ãã
ããã§Data
ãããã¯User
äžèšã®äŸã«ãããshared_ptr<Data>
ããã¯ãªããžã§ã¯ãã®ã³ã³ãã³ãã§ãAnCow
ãæäœã®ã·ãŒã±ã³ã¹ïŒN | éå¶ | 説æ |
---|
1 | ãã㯠| åŒã³åºããããšãã«èªåçã«è¡ãããã¹ãã¬ãŒãžãã㯠operator-> |
2 | ã³ã㌠| ã³ããŒshared_ptr<Data> ãã€ãŸã å®éãã«ãŠã³ã¿ãŒïŒuse_count ããã³weak_count ãªããžã§ã¯ãå
shared_ptr<Data> ïŒã®åçŽãªå¢å ããããŸãã |
3 | ããã¯è§£é€ | äžæãªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ã¹ãã¬ãŒãžã®ããã¯è§£é€ |
ãããã®æäœã®åŸããªããžã§ã¯ãã«å¯ŸããŠããŸããŸãªã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸããèªã¿åãæã«ã¯ã远å ã®ã¢ã¯ã·ã§ã³ã¯çºçããŸãããå æãããããŒã¿é åããçŽæ¥ãªããžã§ã¯ãã®ããŒã¿ãååŸããŠèªã¿åããŸããéåžžã«äºæããªããã¥ã¢ã³ã¹ã«èšåãã䟡å€ããããŸããããã¯ãååŸããã«ãªããžã§ã¯ãããŒã¿ãèªã¿åãããšãã§ããŸãããŸããCOWãè§£æãããšãã«ãã®äºæããªãããããã£ã匷調ãããã£ãã®ã§ãããªããžã§ã¯ãã«ããŒã¿ãæžã蟌ããšã©ããªããŸãããç§ãã¡ã¯èŠãŸãïŒ
ãã®å Žåã®æäœã®é åºã¯æ¬¡ã®ãšããã§ããN | éå¶ | 説æ |
---|
4 | ã¯ããŒã³ | ãªããžã§ã¯ãã®ã¯ããŒã³äœæããªããžã§ã¯ãã¯ã³ããŒã³ã³ã¹ãã©ã¯ã¿ãšåŒã°ããŠData ããŸãããã¹ãŠã®ãã£ãŒã«ããæ°ããã¡ã¢ãªé åã«ã³ããŒããŸãããã®æäœã®åŸã圌shared_ptr ã¯æ°ããäœæããããªããžã§ã¯ããèŠå§ããŸãã |
5 | ä¿®æ£ãã | . , .. . |
6 | ãã㯠| . |
7 | replace | shared_ptr<Data> , 5- . |
8 | unlock | . |
èªæžã®å Žåã®ããã«ããªããžã§ã¯ããèšé²ãããããã¯ããã«çºçããã®ã§ãäœæããããªããžã§ã¯ãã®å¯äžã®ææè
ã§ããååãšããŠãã¿ã€ããªã©ã®åçŽãªã¿ã€ãã®ãªããžã§ã¯ããæäœããå Žåãåããã¿ãŒã³ã®æäœã芳å¯ã§ããŸãint
ã倧ããªéãã¯ãCOWã§ã¯ãè€æ°ã®ã¹ã¬ããã®åãã¡ã¢ãªé åããåæã«ããŒã¿ã䜿çšã§ããããšã§ããäžèšã®æäœã®ã»ãšãã©ã¯èªåçã«è¡ãããããšã«æ³šæããŠãã ããããã¹ãŠã®æäœãæç€ºçã«å®è¡ããå¿
èŠã¯ãããŸãããçã®æé©å
äžèšã®ããã«ãCOWãªããžã§ã¯ãã倿Žãããšããã®ãã¹ãŠã®ãã£ãŒã«ããã³ããŒãããŸããããã¯ãå°éã®ããŒã¿ã§ã¯å€§ããªåé¡ã§ã¯ãããŸãããããããã¯ã©ã¹ã«å€æ°ã®ãã©ã¡ãŒã¿ãŒãããå Žåã¯ã©ãã§ããããïŒãã®å Žåããã«ãã¬ãã«COWãªããžã§ã¯ãã䜿çšã§ããŸããããšãã°ã次ã®ã¯ã©ã¹ãå
¥åã§ããŸãUserInfo
ã struct UserInfo { AnCow<AccountingInfo> accounting; AnCow<CommonInfo> common; AnCow<WorkInfo> work; }; struct AccountingInfo { AnCow<IncomingInfo> incoming; AnCow<OutcomingInfo> outcoming; AnCow<BalanceInfo> balance; }; struct CommonInfo {
åã¬ãã«ã§COWãªããžã§ã¯ããå
¥åããããšã«ãããã³ããŒã®æ°ã倧å¹
ã«åæžã§ããŸããåæã«ãã³ããŒæäœèªäœã¯ãã«ãŠã³ã¿ãŒã®ã¢ãããã¯ãªå¢å ã®ã¿ã§æ§æãããŸãããŸããã³ããŒã³ã³ã¹ãã©ã¯ã¿ã䜿çšããŠå€æŽãªããžã§ã¯ãèªäœã®ã¿ãã³ããŒãããŸããåã¬ãã«ã®ãªããžã§ã¯ãã®æ°ã3 mã«çããå Žåãã³ããŒã®æå°æ°ãéæãããããšãç°¡åã«ç€ºãããŸããäžè¬åãããã¹ããŒã
ãã¹ãã£ã³ã°ãèæ
®ããŠãCOWã®æäœãããè©³çŽ°ã«æ€èšããã®ã§ãèæ
®ãããã€ãã£ãªã ã®äœ¿çšã®äžè¬åã«å®å
šã«é²ãããšãã§ããŸãããããããã®ããã«ãæåã«äŸã§äœ¿çšãããã¹ããŒã ãæ€èšããŸããæåã®äŸã§ã¯ããã¹ããããAnRWLock
ãªããžã§ã¯ãã䜿çšãã
ãŸãããæå®ãããäŸã®Key-Valueã¹ãã¬ãŒãžã¯ã·ã³ã°ã«ãã³ã«é
眮ããããã¹ããŒãããã¥ãŒããã¯ã¹ã§ã©ãããããŠããŸããå€ãã¹ããŒããã¥ãŒããã¯ã¹ã§ã©ãããããŸãããæ¬¡ã®å³ã¯ãCOWã䜿çšããäŸã瀺ããŠ
ããŸããããã§ã¯AnCow
ãCOWã»ãã³ãã£ã¯ã¹ãå®è£
ããããã«ãå€ããªããžã§ã¯ãã«ã©ãããããŠããŸãããããã£ãŠãäžè¬åã¹ããŒã ã¯ä»¥äžã®ããã«æžãããšãã§ãã
ããã¯ããªããžã§ã¯ãããšã¯æããã§ããAnLock
ãšAn(RW)Lock
亀æå¯èœïŒã©ã¡ããäžæ¹ã䜿çšã§ããŸãããŸãããã§ãŒã³ãè¯ãã以äžã®äŸã®ããã«ãæ°åç¹°ãè¿ãããšãã§ããŸãã
ãããããªããžã§ã¯ãã®æå³è«ãšããããšãå¿ããŠã¯ãªããªãAn(RW)Lock
ãšã¯AnCow
倧ããç°ãªããŸããç©ä»¶ | ã¹ããŒããã¥ãŒããã¯ã¹ | ç |
---|
ãªããžã§ã¯ããã£ãŒã«ããžã®ã¢ã¯ã»ã¹ | èªã¿åã/æžã蟌ã¿äžã¯ããã¯ãããŠããŸã | ãããã¯ãããŠããŸãã |
ã³ã³ããå
ã®ãªããžã§ã¯ãã倿Žãã | ã€ã³ãã¬ãŒã¹å€æŽ | 倿ŽåŸãæ°ããå€ãã³ã³ããã«æ»ããŸã |
çµè«
ãã®ããããã®èšäºã§ã¯ããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã®äœæå¹çãåäžãããããã€ãã®ã€ãã£ãªã ã«ã€ããŠæ€èšããŸãããæ¬¡ã®å©ç¹ã¯æ³šç®ã«å€ããŸãã- ã·ã³ãã«ãããã«ãã¹ã¬ããããªããã£ããæç€ºçã«äœ¿çšããå¿
èŠã¯ãªãããã¹ãŠãèªåçã«è¡ãããŸãã
- . . ( ) .
- . , (race condition) (deadlock). . (fine-grained) , .
ãã®ãããªæ®éçãªã¢ãããŒããå¯èœã«ãªã£ãã®ã¯ãAn
-classes ã®å®è£
ã«ãããŠãä¿åããããªããžã§ã¯ãã®äœ¿çšãå®å
šã«å¶åŸ¡ã§ãããšããäºå®ã®ããã§ãããããã£ãŠãå¿
èŠãªæ©èœã远å ããŠãã¢ã¯ã»ã¹å¢çã§å¿
èŠãªã¡ãœãããèªåçã«åŒã³åºãããšãå¯èœã«ãªããŸãããã®ã¢ãããŒãã¯ã次ã®èšäºã§å€§å¹
ã«æ·±åããã³æ¡åŒµãããŸããäžããããçŽ æã§ã¯ã倿
çãªãªããžã§ã¯ãã®äœ¿çšã¯èæ
®ãããŠããŸããã§ãããç¹ã«ãå®è£
AnCow
ã¯åããã³ãã¬ãŒãã¯ã©ã¹ã§ã®ã¿æ©èœããŸãã宣èšãããåã®ã³ããŒã³ã³ã¹ãã©ã¯ã¿ãŒã¯åžžã«åŒã³åºããT
ãŸããæ¬¡ã®èšäºã§ã¯ãããäžè¬çãªã±ãŒã¹ã®å®è£
ã«ã€ããŠèª¬æããŸãããŸãããªããžã§ã¯ãã®çµ±äžãšãã®äœ¿ç𿹿³ããããããŸããŸãªæé©åããã«ãã¹ã¬ãããªã³ã¯ãªã©ã«ã€ããŠèª¬æããŸãããæåŠ
[1] HabrahabrïŒã·ã³ã°ã«ãã³ãã¿ãŒã³ã®äœ¿çš[2] HabrahabrïŒã·ã³ã°ã«ãã³ãšãªããžã§ã¯ãã©ã€ãã¿ã€ã [3] HabrahabrïŒäŸåé¢ä¿ã®å転ãšãã¶ã€ã³ãã¿ãŒã³ã®çæ[4] HabrahabrïŒãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã§ã®ã·ã³ã°ã«ãã³ã®å®è£
[5] WikipediaïŒ ç«¶åç¶æ
[6] Wikipedia ïŒçžäºããã¯[7] ãŠã£ãããã£ã¢ïŒãªãŒããŒâã©ã€ã¿ãŒããã¯[8] ãŠã£ãããã£ã¢ïŒæžã蟌ã¿äžã®ã³ããŒ[9] HabrahabrïŒãã«ãã¹ã¬ãããäžè¬ããŒã¿ããã³ãã¥ãŒããã¯ã¹[10] HabrahabrïŒã¯ãã¹ãã©ãããã©ãŒã ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³[11] HabrahabrïŒã¹ããªãŒã ãããã¯ã C ++ 11ã®æ¡ä»¶å€æ°[ããŒã2][12] HabrahabrïŒC ++ 11ã®ã¹ããªãŒã ãããã¯ãããã³æ¡ä»¶å€æ°[ããŒã1][13] HabrahabrïŒãã¥ãŒããã¯ã¹ã®ãããããã¯ãé²ãããã®2ã€ã®ç°¡åãªã«ãŒã«[14] DrDobbsïŒåæå€ã§æ£ããMutexã®äœ¿çšã匷å¶ããPSã³ããŒæ°ã«é¢ããåé¡ã®è§£æ±ºç,
n
, â
k
, â
a
.
a = n^k
,
k = ln a/ln n
.
ln
k = a/n
. = n*k
(
n
). ã€ãŸã
= n*ln a/ln n
n/ln n
, ..
a
â const. ,
n = e
, 3.
ãããŠæåŸã«-調æ»ãè°é¡ã«ã¯2ã€ã®è³ªåããããŸãã