ãªããžã§ã¯ãã®åŸã«ãªããžã§ã¯ããäœæããå Žåãåçã¡ã¢ãªå²ãåœãŠãªã©ã®ãäºçŽ°ãªããšãã«æ³šæãæããªãããšããããããŸãã ã³ããŒãšã·ãªã¢ã«åã«å ããŠãããŒãããæ°ããã¡ã¢ãªãå²ãåœãŠããšãC ++ã®é床ã®å©ç¹ãåŸã ã«ç¡å¹ã«ãªããŸãã 倧åãªæ°ãããã®ãããéäžçã«äœ¿çšããã°ããã»ã©ãã¡ã¢ãªãäžè¶³ããæçåãããããããæ¹æ³ã§ãªãŒã¯ãçºçãããããã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠã¯é£ãããªããŸãã 䟿å©ã§ãããããã©ãŒãã³ã¹STLã³ã³ãããŒã«ã¯æé»çã«å±éºã§ãããã¯ã¿ãŒãã¹ããªã³ã°ãããã¯ããããã¯ããã§ã«ãã®éåœã«é¥ã£ãŠããŸãã 倧éã®å°ããªãªããžã§ã¯ãã®å²ãåœãŠã®é床ãèœãšãã®ã¯ç¹ã«æ®å¿µã§ãã ããããã¹ã¿ãã¯äžã®ãã®ãããªãªããžã§ã¯ãã®ã¡ã¢ãªã®é 眮ãåŠçããæ¹æ³ããããŸãããç¹å¥ãªããŒã¿ã¯ã©ã¹ã§å®è£ ã®è©³çŽ°ãé ããŸãã ããã¯ãæ°ããé 眮ã®ã¡ã«ããºã ã«åœ¹ç«ã¡ãŸããããã¯ãããŒãããé »ç¹ãã€å°éã®ã¡ã¢ãªå²ãåœãŠã§ãã£ã±ãã®ã¢ããªã±ãŒã·ã§ã³ãæé©åããããã®æ¯é¡ã®ãªãæ¹æ³ã§ãã
ååã®ã¬ãã¹ã³ã§ã¯ãé©ãã¹ãããšãè¡ããŸãããå®è¡æã«èšç®ãããåçã«å ¥åãããåã®å€ãå«ãã³ã³ãããšããŠC ++ãªããžã§ã¯ããæäœããŸããã ãªããžã§ã¯ããžã®å ¥åæã«ãå®éã®ããŒã¿åãåç §ããstd :: shared_ptrãä»ããŠã³ããŒãªã³ã©ã€ãã¢ããªã³ãç©æ¥µçã«äœ¿çšããŸããã ãŸããä»»æã®ããŒã¿åæåã«ã¡ã¢ãªãåçã«å²ãåœãŠãä»»æã®åã®æ°ããããŒã¿ãå¿ èŠã«ãªããã³ã«newãåŒã³åºãããšãç解ãããŸããã
ãã®ã¢ãããŒãã«ã¯å©ç¹ããããŸãã ããŒã¿ã¯è€æ°ã®ãªããžã§ã¯ãéã§å ±æãããã³ããŒãé 延ããå¯èœæ§ããããŸãã ååãšããŠãããŒã¿åã«ã€ããŠäºåã«äœãç¥ãããšã¯ã§ããŸããã ãã ãããã®æ¹æ³ã«ã¯å€ãã®æ¬ ç¹ããããŸããããã¯ãéåžžã«å€§ããå¯èœæ§ã®ãããªããžã§ã¯ãã«å¯ŸããŠãã³ããŒãªã³ã©ã€ããååãšããŠäœ¿çšãããããã§ãã
æåã®æ¬ é¥ã¯ããã«æããã«ãªããŸãã 倧éã®åçã¡ã¢ãªå²ãåœãŠã¯ãããã°ã©ã å®è¡ãç¹ã«newãä»ãã倧éã®æé»çãªã¡ã¢ãªå²ãåœãŠãå€§å¹ ã«é ãããŸãã ã¯ããstd :: stringãšstd :: vectorã®äž¡æ¹ãç¥ã£ãŠããŸããå€ãã®å Žåãããã°ã©ãã«ç¢ºèªããããšãªããã¡ã¢ãªã®åå²ãåœãŠãéå§ãã次ã ãšæ°ãããã®ãåŒã³åºããŸãïŒãããŠãstd :: vectorãžã®ããŒã¿ã®ç§»åã«ã€ããŠã説æããŸãïŒã C ++éçºã®åªããå°é家ã¯ãæšæºã³ã³ããã®ãããã®é¢çœãæ©èœãåžžã«ç¥ã£ãŠãããæ°ããã¡ã¢ãªã»ã°ã¡ã³ããå²ãåœãŠãããã®äžå¿ èŠãªè²»çšãåé¿ããæ¹æ³ãç解ããŠããŸãã çŽç²ãªCãåžžã«é©ããŠããã®ã¯ãã¡ã¢ãªã䜿çšããäœæ¥ãééçã«å®è¡ãããããã§ããC++ã§ã¯ãã¡ã¢ãªã䜿çšããæé»çãªäœæ¥ã®ãã¹ãŠã®ã±ãŒã¹ãåžžã«å¿µé ã«çœ®ãå¿ èŠããããŸãã
2çªç®ã®æ¬ ç¹ã¯æåã®æ¬ ç¹ã§ãã ã¡ã¢ãªã®å°ããªã»ã°ã¡ã³ãã倧éã«é »ç¹ã«å²ãåœãŠããšãã¡ã¢ãªã®ã²ã©ãæçåãçºçããããšãã°åãstd ::ãã¯ã¿ãŒãŸãã¯std ::æååãåæåããããã«ãããªãå°ããªã¡ã¢ãªãããã¯ã1ã€ã®ããŒã¹ã«å²ãåœãŠãããšãã§ããªããªããŸãã ãã®çµæãæãããªçç±ããªãbad_allocãååŸããŸãã å¿ èŠä»¥äžã®ã¡ã¢ãªããããŸãããã¡ã¢ãªãéåžžã«æçåãããŠããç¶æ³ã§ã¯ãå°ããªãµã€ãºã®é£ç¶ãããã¯ãå²ãåœãŠãããšã¯ã§ããŸããã
ãããã£ãŠãã¹ã¿ãã¯ã«ç°¡åã«é 眮ã§ããint64_tã«å¹æµããå°ããªãªããžã§ã¯ãã«ã¯ãå¥ã®ããŒã¿åŠçæè¡ã䜿çšã§ããŸãã ãã®ãããªãªããžã§ã¯ãã¯å€æž¡ãã§ããŸãã1ã€ãŸãã¯2ã€ã®ã¬ãžã¹ã¿ãç°¡åã«ã³ããŒããããããæåã®å€æŽãŸã§é 延ããããšãªããäœåºŠã§ãã³ããŒã§ããŸãã
åæã«ãå®è£ æã«ããŒã¿ã®è©³çŽ°ã宣èšããæ £è¡ããéžè±ããã¹ãã§ã¯ãããŸããã ãã ããäœããç ç²ã«ããå¿ èŠããããŸããããŒã¿ã®æ£ç¢ºãªãµã€ãºããã€ãåäœã§äºåã«ç¥ãå¿ èŠããããŸãã éåžžã®ããŒã¿ãã€ã³ã¿ãšäžç·ã«ãªããžã§ã¯ãããŒã¿ãé 眮ããããã«ãã¯ã©ã¹ã«ãããã¡ãä¿æããããã«å¿ èŠã«ãªããŸãã ãã詳现ã«ã
ãã¡ãŒã¹ãã¯ã©ã¹
å€åŽã§ã¯ãã»ãšãã©äœãå€ãããŸããã APIãªããžã§ã¯ããæäŸãããã¹ãŠã®åãã¯ã©ã¹ã ãã®ã¯ã©ã¹ã«ã¯ãåæ¹å®£èšã«ãã£ãŠå®£èšãããã¯ã©ã¹ã®ããŒã¿ãžã®ãªã³ã¯ãå«ãŸããŠãããå®è£ ã®è©³çŽ°ã§ã¬ã³ããªã³ã°ãããŸãã ãã®ãããã¯ã©ã¹ãã£ãŒã«ãã«ãã®åã®ãªããžã§ã¯ãã宣èšããããšã¯ã§ããŸããããåçŽãªãã€ã³ã¿ãŒã§ããŒã¿åãåç §ããåããªããžã§ã¯ãã«ãªããžã§ã¯ãããŒã¿ãæ ŒçŽããããã®ãããã¡ãŒãäºåã«èšå®ã§ããŸãã ããšãã°ãã¹ã¿ãã¯äžã«ãªããžã§ã¯ããäœæãããå Žåããã¹ãŠã®ããŒã¿ã¯ãªããžã§ã¯ãã®äžéšãšããŠã¹ã¿ãã¯ã«ä¿åãããŸãã 次ã«ããã¹ãŠãé©åã«é 眮ãããããã«äŸãèããŸãã
class object { public: ... protected: // class data; // static const size_t max_data_size = N; private: // data* m_data; // , char m_buffer[max_data_size]; };
ãã®ã³ãŒãã§ã¯ãå®è£ ã§ããŒã¿ãé ããšããã€ããªãã®ãŒãç¶ããŠããŸããã¯ã©ã¹ããŒã¿ã«ã€ããŠç¥ã£ãŠããã®ã¯ãã¯ã©ã¹ã®ååãšããŒã¿ãžã®ãã€ã³ã¿ãŒã®ååšã ãã§ãã ãã ããçŸåšã¯ããŒãå ã§ã¡ã¢ãªäžè¶³ãåé¿ããæ©äŒããããŸãã C ++ã®çšèªã§ã¯ãã¯ã©ã¹ã¯ãã£ãŒã«ãã®åœ¢åŒã§ããŒã¿ãä¿åããŸãã å®éãããŒã¿ã¯m_bufferãããã¡ãŒã«é 眮ãããŸããm_bufferãããã¡ãŒã¯ãã¯ã©ã¹ãäœæããããšãã«æ¢ã«å²ãåœãŠãããã¡ã¢ãªã§ãã ãã€ããããã¡ã«ããŒã¿ãé 眮ããæ¹æ³ã®è©³çŽ°ã説æããã ãã§ãã
æ°ãããã¹ãã£ã³ã°
ååãšããŠãäœæããããªããžã§ã¯ããé 眮ããããã®æ¢è£œã®ã¡ã¢ãªé åãæå®ããæ©èœãšããŠãnewæŒç®åã®ãã®ãããªæçšãªããããã£ãèãã人ã¯ã»ãšãã©ããŸããã å¿ èŠãªã®ã¯ãå²ãåœãŠããããããã¡ã«ä»»æã®ã¿ã€ãã®ãªããžã§ã¯ããäœæããããã«ãæ°èŠïŒm_bufferïŒãæžã蟌ãããšã ãã§ãã ç°¡åã«èãããŸãããæ倧ãããã¡ãµã€ãºãäºåã«æå®ãããšããé«ãäŸ¡æ Œãæ¯æãããšãèŠããŠããå¿ èŠããããŸãã ããã ãã§ãªãããââããã¡ã®ãµã€ãºã¯ããããŒãã¡ã€ã«ã«åãŸããAPI宣èšã«æ瀺çã«é¢äžããŸãã
ããããæã ã¯ã¹ããŒãã§åã¡ãŸãã åæåããšã«ããŒãã«ããŒã¿ãå²ãåœãŠãããšã§ãJavaã«é ãããšããªã¹ã¯ãçºçããå Žåããã¹ãŠã®ããŒã¿ãã¹ã¿ãã¯ã«é 眮ããããšã§ãçŽç²ãªsié床ïŒC ++ãé€ãã»ãšãã©ãã¹ãŠã®é«ã¬ãã«èšèªã§éæäžå¯èœãªé床ïŒãåŸãããŸãã åæã«ãæœè±¡åã®ã¬ãã«ã¯éåžžã«é«ããéåžžã®C ++ãªããžã§ã¯ãã«APIãæ§ç¯ããå®è£ ã®è©³çŽ°ãé ããŸãã å¯äžã®å¶éã¯ãèšå®ãããµã€ãºã§ãã å®è£ å ã®ããŒã¿ã¯ã©ã¹ã®ãã£ãŒã«ãã»ãããç°¡åã«å€æŽããããšã¯ã§ããªããªããŸããããµã€ãºãåžžã«èŠããŠããå¿ èŠããããŸãã ããã«ãå®è£ ã«èšè¿°ãããŠããããŒã¿ã®ãµã€ãºããã§ãã¯ããŠãããããŒãã¡ã€ã«ã§æå®ãããŠããããŒã¿ã«æºæ ããå¿ èŠããããŸãã ã©ã€ãã©ãªã®ã¢ã»ã³ããªãããããŒãã¡ã€ã«ã®ããŒãžã§ã³ãšç°ãªãå Žåãããã®ã¯ãããšãã°ããŸããŸãªãœãŒã¹ããåä¿¡ããå Žåãªã©ã§ãã ãã®ãããªãã§ãã¯ããnewãé 眮ããããšã«ãã£ãŠæºåãããã¡ã¢ãªã«ãªããžã§ã¯ããäœæããããã«èŠããæ¹æ³ã®äŸãèŠãŠã¿ãŸãããã
object::object() : m_data(new(m_buffer) object::data) { static_assert(sizeof(object::data) <= max_data_size, "..."); }
ããã§ãstatic_assertã¯ã³ã³ãã€ã«æ®µéã§å®éã«å®è¡ããããããm_dataã¯ãªããžã§ã¯ã::ããŒã¿çšã«m_bufferãããã¡ãŒã«ååãªã¡ã¢ãªãããå Žåã«ã®ã¿åæåãããŸãã åæ§ã«ããªããžã§ã¯ãã¯ã©ã¹ã®äžäœã¯ã©ã¹ïŒããšãã°ãflowerïŒã§ã¯ãããŒã¿ãåºæ¬ã¯ã©ã¹ã®å®è£ ã«æ ŒçŽããããããããŒã¿ãæå®ãããããŒãè¶ ããŠã¯ãªããŸããã
flower::flower(std::string const& name) : object(new(get_buffer()) flower::data(name)) { static_assert(sizeof(flower::data) < max_data_size, "..." ); }
æããã«ãããã«ã¯ããªããžã§ã¯ã::ããŒã¿*ãããªããžã§ã¯ãã®ä¿è·ãããã³ã³ã¹ãã©ã¯ã¿ãŒãšåæ§ã«ãåºæ¬ã¯ã©ã¹ã®m_bufferã¢ãã¬ã¹ãååŸããããã«get_bufferïŒïŒprotectedã¡ãœãããå¿ èŠã§ãã åã®ãªãªãŒã¹ã®ããã«ãåºæ¬ã¯ã©ã¹ã®ããŒã¿ããçžç¶äººã®ããŒã¿ãç¶æ¿ãããããflower :: data *ã¯object :: data *ãšäºææ§ããããŸãã ã»ãã¥ãªãã£ã®ããã«ãobject :: data *ããåºæ¬ã³ã³ã¹ãã©ã¯ã¿ã«è¿œå ãã䟡å€ããããŸãã以åã«å²ãåœãŠããããããã¡ã®ã¢ãã¬ã¹ãæž¡ãããããšã確èªããŸãã
object::object(object::data* data_ptr) { if (static_cast<void*>(data_ptr) != static_cast<void*>(m_buffer)) throw some_exception(...); m_data = data_ptr; }
ãã®çµæã以åãšåæ§ã«ãéåžžã®ã¯ã©ã¹ãªããžã§ã¯ããæäœããããšã§åçåä»ãããšãã¥ã¬ãŒãã§ããŸãã ããšãã°ã次ã®ããã«ïŒ
object rose = flower("rose");
倧ããªããŒã¿ãªããžã§ã¯ã
ããŒã¿ãµã€ãºãæå®ãããæ倧å€ãè¶ ãããªããžã§ã¯ããã©ãããããèŠã€ããããšã¯æ®ã£ãŠããŸãã å®éãããã®ãã¹ãŠã¯éåžžã«ç°¡åã§ãã copy_on_write <data :: impl>ã®ãµã€ãºãå¶éã«åãŸãã ãã§ååã§ããããã¯ãæ¬è³ªçã«std :: shared_ptr <data :: impl>ã®ã¢ããªã³ã§ããããã§ãimplã¯ä»»æã®ãµã€ãºã®ããŒã¿ââã¯ã©ã¹ã®å®è£ ã§ãã std :: shared_ptr <data :: impl>ã®ãµã€ãºã¯ãdata :: implã¯ã©ã¹èªäœã®ãªããžã§ã¯ãã®ãµã€ãºã«äŸåããªããããå€ã«ããã¹ãã¬ãŒãžããåç §ã«ããã¹ãã¬ãŒãžãžã®ç§»è¡ã§ããŒã¿ãæ ŒçŽããæ®éçãªæ¹æ³ãååŸããŸãã
class huge { public: ... protected: class data; }; class huge::data { public: ... protected: class impl; private: copy_on_write<impl> m_impl; };
ãã ããåçåä»ãã䜿çšãããªããžã§ã¯ãçšã®åäžAPIã®åé¡ã®è§£æ±ºçããè±åŽããæ°ããé 眮ã«ããæé©åã®å¥ã®äŸãèããŠã¿ãŸãããã
copy_on_write ::ãã©ãã·ã¥ããã¯
誰ãã以åã®ãªãªãŒã¹ãã¹ãããããå Žåãcopy_on_writeã¯ã©ã¹ã¯ã³ããŒæé©åã§ããŒã¿ãä¿åããããã®ãã³ãã¬ãŒãã¯ã©ã¹ã§ãã ãã€ã³ã¿ãŒããšãã¥ã¬ãŒããããã®ã¯ã©ã¹ã«ã¯ãconstããã³non-constã®å Žåã®ããªãããŒãªoperator->ãªãŒããŒããŒãããããŸãã ãªããžã§ã¯ããã³ããŒãããšããé«äŸ¡ãªã³ããŒãåŒãèµ·ããããšãªãåãããŒã¿ãåç §ããŸãã ãã ããããŒã¿ãæœåšçã«å€æŽããããŒã¿ã¯ã©ã¹ã®éå®æ°ã¡ãœãããåŒã³åºããšããã«ãçŸåšã®ãªããžã§ã¯ãã®ããŒã¿ã®ã³ããŒããã¿ããããŸãã ç°¡çŽ åãããå®è£ ã¯æ¬¡ã®ããã«ãªããŸãã
template <typename impl_type> class copy_on_write { public: copy_on_write(impl_type* pimpl) : m_pimpl(pimpl) { } impl_type* operator -> () { if (!m_pimpl.unique()) m_pimpl.reset(new impl_type(*m_pimpl)); return m_pimpl.get(); } impl_type const* operator -> () const { return m_pimpl.get(); } private: std::shared_ptr<impl_type> m_pimpl; };
ãããã£ãŠãçµã¿èŸŒã¿ãããã¡ã®æ倧ããŒã¿ãµã€ãºãéžæããå Žåããã£ãŒã«ããšããŠcopy_on_writeãå«ãã¯ã©ã¹ã®ãµã€ãºãèæ ®ãã䟡å€ããããŸãã
ããŒã¿ãã£ãŒã«ã
ãã¹ãnewãä»ããŠæé©åããæã匷åãªæ¹æ³ã¯ãSQLã¯ãšãªã®éžæã¬ã³ãŒãã®ãã£ãŒã«ãã䜿çšããããšã§ãã ãµã³ãã«ã¯ãæŽæ°ãå®æ°ããæååãé åãŸã§ãããŸããŸãªã¿ã€ãã®ããŒã¿ã»ãããèŠæ±ããŸãã ããŒã¿èªäœã¯åçã«ååŸãããããŒã¿ããŒã¹åŽããååŸããããã£ãŒã«ãã¿ã€ãã¯åçåä»ããšãã¥ã¬ãŒã·ã§ã³ã§åæåããå¿ èŠããããŸããããã¹ãŠã®ã¬ã³ãŒãã«ã¯ãåã¬ã³ãŒãã®åèšããŒã¿ãµã€ãºã決å®ã§ããåããã£ãŒã«ãã¿ã€ãã®ã»ãããå«ãŸããŠããŸãã ããã«ãããã¬ã³ãŒããã£ãŒã«ãã«ã¡ã¢ãªã1åã ãå²ãåœãŠãããšãã§ããéžæããåã¬ã³ãŒãã«å«ãŸãããã£ãŒã«ãã®ã¿ã€ãã«å¿ããŠãµã€ãºãèšç®ãããŸãã ãŸããåäžã®ãŠããããšããŠãã¹ãŠã®ã¬ã³ãŒãã«äžåºŠã¡ã¢ãªãå²ãåœãŠãããšãå¯èœã§ãããååãšããŠãã¬ã³ãŒããååŸããåŸããã£ã«ã¿ãªã³ã°ã䞊ã¹æ¿ããå«ãããããçš®é¡ã®æäœãå®è¡ããããããåŸç¶ã®æäœã®äŸ¿å®ã®ããã«ã¬ã³ãŒãèªäœãã³ããŒãªã³ã©ã€ããªããžã§ã¯ããšããŠèšè¿°ããããšã¯çã«ããªã£ãŠããŸãã åãã£ãŒã«ãã«ããŒãããã¡ã¢ãªãå²ãåœãŠãã®ã¯äžåœã«é«äŸ¡ã§ãã
ããã¯ã宣èšãåçŽåããããŒã¿ã¯ã©ã¹ããçŽæ¥copy_on_writeã䜿çšããå Žåã®ã¬ã³ãŒãã¯ã©ã¹ã®å€èŠ³ã§ãã
class record { public: record(std::vector<field::type> const& types); ... protected: class data; private: copy_on_write<data> m_data; }; class record::data { public: data(std::vector<field::type> const& types); ... private: std::vector<char> m_buffer; std::vector<field*> m_fields; };
ããã§ã¯ã説æãç°¡åã«ããããã«ããã£ãŒã«ãã¿ã€ãã®ãã¯ãã«std :: vector <field :: type>ãenumå€ã®é åãå°å ¥ãããŠããŸãã å®éããã®é åã¯ãboost :: fusionãä»ããŠåŒæ°ããåæå®ããããBoost.Preprocessorã䜿çšããŠãä»»æã®åã®åŒæ°ããåãªããžã§ã¯ãã®æ±çšãªããžã§ã¯ãã®é åããã€ã€ã«ããå¿ èŠããããŸãã åã¬ã³ãŒãã®ããŒãããã¡ã¢ãªãåäžã«å²ãåœãŠãã¡ã«ããºã ã¯ãä»ã§ã¯éèŠã§ãã
record::data::data(std::vector<field::type> const& types) : m_buffer(field::calc_size(types)), m_fields(types.size()) { size_t offset = 0; std::transform(types.begin(), types.end(), m_fields.begin(), [&offset](field::type type, field*& field_ptr) { field_ptr = new(m_buffer + offset) field(type); offset += field::size(type); } ); }
ããã§ãfield :: sizeã¯æž¡ãããfield :: typeããããŒã¿ã®ãµã€ãºãèšç®ããfield :: calc_sizeã¯ãã§ã«std :: vector <field :: type>ãšããŠæž¡ãããã¬ã³ãŒãã¿ã€ãã®ã»ããå šäœã«å¿ èŠãªåèšãµã€ãºãèšç®ããŠããŸãã
ãã£ãŒã«ããã£ãŒã«ãã¯ãåºæ¬çã«åçã³ã³ãã³ãã®ã³ã³ããã§ãããªããžã§ã¯ãã¿ã€ããšåæ§ã«å®è£ ãããŸãã ã»ãšãã©ã®åïŒint64_tãboolãdoubleã¯ã¹ã«ã©ãŒã§ãããå€ã«ãã£ãŠæ ŒçŽãããŸãã std ::æåååãå€ã§ä¿åã§ããŸãããæååããŒã¿ãã»ãŒç¢ºå®ã«ããŒãã«ä¿åãããåçã«å²ãåœãŠãããããšãèæ ®ãã䟡å€ããããŸãã ç¹å®ã®é·ãã®ç¹å®ã®varcharããµããŒãããå Žåãã»ãšãã©ã®å Žåãåºå®é·ã®æåã®é åãæã€ç¬èªã®åcopy_on_writeãå¿ èŠã«ãªããŸãã
ããŸããŸãªã¿ã€ãã®ãã£ãŒã«ãã¯ããªããžã§ã¯ãã¯ã©ã¹ããç¶æ¿ãããããŸããŸãªã¿ã€ãã®ãªããžã§ã¯ãã«äŒŒãŠããŸãã enumã䜿çšããããšãã§ããŸããããåã«çŽæ¥çµã³ä»ããããŸãããååãšããŠãSQLã¯ãšãªã®çµæã解æããã«ã¯ããã¹ãŠã®ãã£ãŒã«ãåãäºåã«ããã£ãŠããããŒã¿ã®ãã€ããã±ãããéã·ãªã¢ã«åããå¿ èŠããããŸãããããã£ãŠãenumã«ã¯å¶éããããŸããã ããã«ãã¡ã¿ããã°ã©ãã³ã°ã¯æ°åŒ±ãªäººåãã§ã¯ãªããããããã§ã¯MPLãšBoost.Fusionãæ€èšããŸããã
æ°ãããã¹ãã䜿çšããæåŸã®éèŠãªåŽé¢ãã€ãŸãC ++ã®åãã¿ã€ãã®ãªããžã§ã¯ãã®ããŒã«ã«ã€ããŠã¯è§ŠããŠããŸããã
åãã¿ã€ãã®ãªããžã§ã¯ãã®ããŒã«
åãšåæ§ã«ãåçã¡ã¢ãªå²ãåœãŠãæé©åããŠããŸãã ãªããžã§ã¯ãããŒã«ãšã¯äœã§ããïŒ ããã¯ãç¹å®ã®ã¿ã€ããåæåããããã«å€§å¢ã®äººã«ãã£ãŠäºåã«å²ãåœãŠããããã©ã³ã¯ã®é åã§ãã ããæå³ã§ã¯ãäžèšã®ã¬ã³ãŒãã¯ãã£ãŒã«ããªããžã§ã¯ãã®ããŒã«ã§ããã ãŸããé«ã¬ãã«èšèªïŒCïŒãPythonãJavaïŒã§äœæ¥ããŠããå Žåããªããžã§ã¯ãã®ããŒã«ã«åºäŒã£ãå¯èœæ§ããããŸãããããã¯ãæºåãããã¡ã¢ãªã»ã°ã¡ã³ãã䜿çšããŠããªããžã§ã¯ããé 眮ããæ°ãããªããžã§ã¯ããå²ãåœãŠãŸããå®éã«ã¯ãã¿ã€ãã¯ãªããžã§ã¯ãã§ãã ããŒã«ãªããžã§ã¯ãã®1ã€ãäžèŠã«ãªã£ãåŸãã€ãŸããåç §ãããªããªã£ãåŸãããã«åæå解é€ãããããã¬ããŒãžã³ã¬ã¯ã¿ãŒãã¬ããŒãžã³ã¬ã¯ã¿ãŒãææè ã®ããªãååãåé€ããããã®ç¹å¥ãªã¡ã«ããºã ã®æ¬¡ã®ãã€ãã¹ã®åœ¢ã§æ²ããéåœãåŸ ã£ãŠããŸãã äžè¬çã«ãããŒã«å ã®ãªããžã§ã¯ãã®åæå解é€ã¯ãã®åŒ±ç¹ã§ãã ããããéåžžã¯ãã§ã«åæåãããŠããããåæåã®æºåãã§ããŠãããªããžã§ã¯ãã®è¿ éãªéžæãååŸããŸãã ãªããžã§ã¯ãã¿ã€ãã«åºã¥ããŠãåç §ã«ãŠã³ãã«ããåæå解é€ãšã¬ããŒãžã³ã¬ã¯ã¿ãŒãåããæ¬æ Œçãªãªããžã§ã¯ãããŒã«ãäœæãããšãJavaãŸãã¯PythonãåŸãããŸãã ãã®ãããªãã®ãå¿ èŠãªå Žåãåºãå²ãããã¿åéã§æ¢è£œã®èšèªãåãã¹ãã§ã¯ãªãã§ããããïŒ ãã ããåãã¿ã€ãã®ãªããžã§ã¯ãã®æé©åã®ããã«ãäºåã«å€§éã®ã¡ã¢ãªã»ã°ã¡ã³ããå²ãåœãŠãå¿ èŠããããã¿ã¹ã¯ãå®éã«ç¹å®ã®åºæ¬ã¯ã©ã¹ãæã€å€æ°ã®ãªããžã§ã¯ãã®å€§éåæåãå¿ èŠãšããå Žåããªããžã§ã¯ãã®ããŒã«ã«ããã倧éã®åçã¡ã¢ãªå²ãåœãŠãåé¿ã§ããŸãã
ç解ããã«ã¯ãæ確ã§å¿çšçãªèª¬æãå¿ èŠã§ãã ã¬ã³ãŒãã®ããŒã«ã䜿çšããSQLã¯ãšãªã®çµæãšããŠå®éã«ãã§ããããã®ã¯ã©ãã§ããïŒ ããã«ããããµã³ãã«ã¬ã³ãŒããªããžã§ã¯ããæ§ç¯ããããã®ã¡ã¢ãªå²ãåœãŠã®è³ªéãæé©åãããŸãã
class selection { public: selection(std::vector<field::type> const& types, size_t row_count); ... protected: class data; private: copy_on_write<data> m_data; }; class selection::data { public: data(std::vector<field::type> const& types, size_t row_count); ... private: std::vector<field::type> m_types; std::vector<char> m_buffer; std::vector<record> m_rows; }; selection::data::data(std::vector<field::type> const& types, size_t row_count) : m_types(types) { if (!row_count) return; m_rows.reserve(row_count); size_t row_data_size = field::calc_size(types); m_buffer.resize(row_count * row_data_size); char* offset = m_buffer for (size_t i = 0; i < row_count; ++i) { m_rows.push_back(record::inplace(offset, types)); offset += row_data_size; } }
record :: inplaceã¯ãæ¬è³ªçã«ãããŒãã§ã¯ãªããæå®ãããã¢ãã¬ã¹ã«ã¬ã³ãŒãããŒã¿ãäœæããŸãã
record record::inplace(void* address, std::vector<field::type> const& types) { return record(new(address) record::data(types)); }
åæåãšç¹å¥ãªãã¹ãã©ã¯ã¿ãåããã¬ã³ãŒãã³ã³ã¹ãã©ã¯ã¿ãå¿ èŠã§ãã詳现ã¯åŸã§èª¬æããŸãã ã¬ã³ãŒããåæåãããã®ãªãã·ã§ã³ã«ããã以åã®ããŒãžã§ã³ãã€ãŸãcopy_on_writeãã£ãŒã«ãã®ã¿ãå«ãã¯ã©ã¹ã®åœ¢åŒã§ã¬ã³ãŒãã䜿çšããããšãã§ããªããªããŸãã ããŒãäžã®ããŒã¿ã®åçãªå²ãåœãŠã«å·éã«é Œã£ãŠãå¿ èŠã«å¿ããŠã¬ã³ãŒããåãæ¿ããããšã¯ã§ããŸããã äžæ¹ã倧èŠæš¡ãªããŒã¿ã»ããã䜿çšãããšãããã©ãŒãã³ã¹ãå€§å¹ ã«åäžããŸãã ãã ããæ°ããæçš¿ã«ã¯æ³šæãå¿ èŠãªãã£ããããããŸãã
æ瀺çãªãã¹ãã©ã¯ã¿åŒã³åºã
èŠå
誰ããæåŸãŸã§èªãã ããæãã«èªãã ãããªãç¿æ £ãããå Žå-éåžžã«ç¡é§ã§ãã ãã®éèŠãªã»ã¯ã·ã§ã³ãã¹ãããããããšã§ãã¡ã¢ãªãªãŒã¯ïŒå€§éã®ã¡ã¢ãªãªãŒã¯ïŒãçºçãããããšãã§ããŸãã
ãã¹ãnewã䜿çšããå Žåããã1ã€ããããã-åé€ã¯äœãããªãã®ã§ããã¹ãã©ã¯ã¿ãæåã§åŒã³åºãå¿ èŠããããŸãã ãããã£ãŠãäºåã«æºåãããã¡ã¢ãªã«å²ãåœãŠãããããŒã¿ãå«ãã¯ã©ã¹ã¯ããã¹ãã©ã¯ã¿å ã®ã¡ã¢ãªã«äœæãããã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ãæ瀺çã«åŒã³åºãå¿ èŠããããŸãã ãããã£ãŠãã¯ã©ã¹ãã¹ãã©ã¯ã¿ãªããžã§ã¯ã::ããªããžã§ã¯ãã¯ããªããžã§ã¯ã::ããŒã¿::ãããŒã¿ãã¹ãã©ã¯ã¿ãæ瀺çã«åŒã³åºãå¿ èŠããããã¬ã³ãŒã::ããŒã¿::ãããŒã¿ãã¹ãã©ã¯ã¿ã¯ããã£ãŒã«ãããšã«1ã€ã®ãã£ãŒã«ã::ããã£ãŒã«ããã¹ãã©ã¯ã¿ãåŒã³åºãå¿ èŠããããŸãã ãããã©ã®ããã«çºçããããæ確ã«ç€ºãããã«ããªããžã§ã¯ãã¯ã©ã¹ããã詳现ã«èª¬æããŸãã
class object { public: object(); virtual ~object(); ... protected: class data; char* get_buffer(); object(data* derived_data); static const size_t max_data_size = N; private: data* m_data; char m_buffer[max_data_size]; }; object::object() : m_data(new(m_buffer) data) { static_assert(sizeof(data) <= max_data_size, "..."); } object::~object() { m_data->~data(); }
ããŒã¿ã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ã¯ä»®æ³ãšããŠèšè¿°ããå¿ èŠããããããobject :: dataã®ç¶æ¿è ã䜿çšãããŠãããã«é¢ä¿ãªããããŒã¿ã®åæå解é€ã¯æåããŸãã
ãŸããã³ã³ã¹ãã©ã¯ã¿ãŒãšã³ããŒæŒç®åãããã³ç§»åãåå®çŸ©ããå¿ èŠããããŸããããã¯ãèªåçæãããã³ã³ã¹ãã©ã¯ã¿ãŒã«æºè¶³ããcopy_on_writeã®å Žåãšã¯ç°ãªããããã§ã¯åãªããžã§ã¯ããåçŽãªãã€ã³ã¿ãŒã§ããŒã¿é åãåç §ããããã§ãã ãããã£ãŠãããã©ã«ãã®åäœãä¿®æ£ããŸãã
object::object(object const& another) : m_buffer(max_data_size), m_data(another.clone_data_at(m_buffer)) { } object& object::operator = (object const& another) { destruct_data(); // m_data = another.clone_data_at(m_buffer); return *this; } object::data* object::clone_data_at(void* address) { return m_data->clone_at(address); } // // object::data* object::data::clone_at(void* address) { return new(address) data(*this); } void object::destruct_data() { m_data->~data(); }
ããã§ã¯ãæ°ããdesctuct_dataïŒïŒã¡ãœããããã¹ãã©ã¯ã¿ãªããžã§ã¯ã::ããªããžã§ã¯ãã§èŠæ±ãããŠããŸãã äžåºŠå°ãããšã圌ã®ããã®å Žæãããããšãæå³ããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒãšç§»åæŒç®åã®å Žåãåäœã¯åæ§ã§ãã
object::object(object&& another) : m_data(another.move_data_to(m_buffer)) { } object& object::operator = (object const& another) { destruct_data(); // m_data = another.move_data_to(m_buffer); return *this; } object::data* object::move_data_to(void* address) { return m_data->move_to(address); } // // object::data* object::data::move_to(void* address) { return new(address) data(std::move(*this)); } object::~object() { destruct_data(); }
ãããã£ãŠãã¡ã¢ãªãªãŒã¯ã®å±éºæ§ã¯ãªããªããŸãã APIãŠãŒã¶ãŒã¯èœã¡çããŠéçºã§ããŸãã
ããŒãäžã®æ°èŠãã¹ããšæ°èŠãã¹ãã®ãã¹ãã£ã³ã°
æ¢ã«ãæ°ä»ãã®ããã«ãhost newã䜿çšããã¯ã©ã¹ã¯å®è£ ãã¯ããã«å°é£ã§ãã æºåãããã¡ã¢ãªã«ãªããžã§ã¯ããé 眮ããææ³ã§å®è£ ãããã¯ã©ã¹ã䜿çšãããã¹ãŠã®åŽé¢ã培åºçã«ãã¹ãããå¿ èŠããããŸãã éåžžãã¯ã©ã¹ã®éåžžã®æ°ãããã®ã®è€éãã¯ãã¹ããŒããã€ã³ã¿ãŒãã©ããããããšã«ãªããŸãã 次ã«ãããŒã¿åã®æ倧ãµã€ãºãæ瀺çã«æå®ããããšã§åçåä»ãã®ãšãã¥ã¬ãŒã·ã§ã³ã§ããè€éã«ãªãå Žåãã©ã®ãããªå©ç¹ããããŸããïŒ
é床ã®åäžã ãã䟿å©ãªCïŒãJavaãPythonãšæ¯èŒããC ++ã®åã¯ãå®è¡é床ã«ãããŸãã ããã§ã¯ãæ°ãããªããžã§ã¯ãã®ããŒãã«ç§»åããªããããæé«é床ã«éããŸãã ãŸããã¡ã¢ãªã®æçåãåé¿ããŠãå°æ¥ã¢ããªã±ãŒã·ã§ã³ã®é床ãèœãšããªãã§ãã ããã æçåãããèšæ¶ã¯ããŒãºã®ãããªãã®ã§ããç©Žããã£ã±ãã§ããããã®ç©Žã®å€§ããã§ãªã¬ã³ãžãè©°ã蟌ãããšãã§ããŸãããå®éã«ã¯ãªã¬ã³ãžã¯ã©ã®ç©Žã«ãåãŸããããããããå°ããããŸãã ãã®ãããé£ç¶ã¡ã¢ãªã®ã»ã°ã¡ã³ããå¿ èŠãšããstd :: vectorããã³std :: stringã¯ãèŠçŽ ãåé åžãããšãã«ãã€ãstd :: bad_allocãååŸã§ããŸãã
æšæºã©ã€ãã©ãªã®æ°ãããã¹ãã£ã³ã°
èšäºã®åé ã§std :: vectorã«newãé 眮ããããšããçŽæããŸãããïŒ ãã®ãããstd :: vectorã®ãã¹ãŠã®èŠçŽ ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãæºåãããã¡ã¢ãªã§åŒã³åºãããŸãã ãŸãããã¹ãã©ã¯ã¿ã¯èŠçŽ ã«å¯ŸããŠãç©æ¥µçã«åŒã³åºãããŸãã ããã¯ãintãcharãªã©ã®åçŽãªPODåã®ãã¯ã¿ãŒã§ã¯éèŠã§ã¯ãããŸããããstd :: vectorã匷調ãããå Žåãcustomã«éèŠãªããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ãŒãšããã»ã©éèŠã§ã¯ãªãã³ããŒã³ã³ã¹ãã©ã¯ã¿ãŒãããå Žåãããããªããšå€ãã®åé¡ãçºçããŸãstd :: vectorããã®ããŒã¿ãã©ã®ããã«åŠçããããç解ããŸãã
ã§ã¯ããã¯ã¿ãŒã«ãµã€ãºå€æŽãèŠæ±ãããšã©ããªããŸããïŒ ãŸãããã¯ã¿ãŒã¯å¿ èŠãªãã€ãæ°ããŸã äºçŽããŠããªãããã«èŠããŸãïŒãã¯ã¿ãŒã¯åžžã«ããŒãžã³ä»ãã®ãããã¡ãŒãå²ãåœãŠãŸãïŒããã®åŸãæ°ãããããã¡ãŒãå²ãåœãŠãŸãã ãã¹ãŠã®æ¢åã®èŠçŽ ã¯ã移åã³ã³ã¹ãã©ã¯ã¿ãŒã«ãã£ãŠã察å¿ããã¢ãã¬ã¹ã«newãé 眮ããããšã«ãããæ°ãããããã¡ãŒã«è»¢éãããŸãã ãã®çµæããã¹ãŠã®èŠçŽ ãé 眮ãããŸãã ãã®åŸããã¯ãã«ã¯å¿ èŠãªæ°ã®èŠçŽ ãé åã®æåŸãŸã§ååŸããæ°ããããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãé 眮ããŠåèŠçŽ ãäœæããŸãã ãŸãå察æ¹å-èŠçŽ ã®æ°ãæžãããšãèŠçŽ ãåé€ãããšãã«ãã¹ãã©ã¯ã¿ããæåã§ãçºçããŸãã
std :: vectorãšã¯ç°ãªããstd :: stringã³ã³ããã¯ãã³ã³ã¹ãã©ã¯ã¿ããã¹ãã©ã¯ã¿ãå¿ èŠãšããªãcharãåžžã«æ ŒçŽãããšããçç±ã ãã§ãæ°ããé 眮ãåŠçããŸããã ãã ããæšæºã©ã€ãã©ãªã®å€ãã®ã³ã³ããïŒdequeãlistãmapãããã³ä»»æã®ããŒã¿ãæ ŒçŽããããã®ãã®ä»ã®ã¯ã©ã¹ãã³ãã¬ãŒã-å®è£ ã®æ°ãããã¹ãã£ã³ã°ãç©æ¥µçã«äœ¿çšããŸãã
newãããã¯ã®ãããªãã®ãšèããå¿ èŠã¯ãããŸãããæå®ãããã¡ã¢ãªã®ã³ã³ã¹ãã©ã¯ã¿ã§ãªããžã§ã¯ããåæåã§ããæ¬æ Œçãªèšèªæ©èœã§ãã ãã®æäœã¯ãå²ãåœãŠããããã€ããããã¯ãç¹å®ã®ã¿ã€ãïŒéåžžã¯æ§é äœïŒãžã®ãã€ã³ã¿ãŒãšããŠå®£èšããããã®ã¡ã¢ãªãããã¯ã§ã®ãããªãäœæ¥ããã®ã¿ã€ãã®APIã«ãã£ãŠå®è¡ããããå€ãCèšèªã®ããªãã¯ã«äŒŒãŠããŸãã
çµæã¯äœã§ããïŒ
ãã¡ãããå¿ èŠã«å¿ããŠæ°ãããã¹ãã£ã³ã°ã䜿çšããæ©èœã¯ããããæ¬åœã«å¿ èŠãªå Žåã«ã®ã¿ãå¹ççãã€æ£åœãªçç±ã§ãããã«ã¯å®çŸããŸããã ãããã®ããã€ãã¯ãäºåçãªæé©åã®å®³ã«ãã£ãŠæåŸãŸã§æã¡è² ããããŠããŸãããå察ã«ãä»ã®äººã¯ãèšäºãèªãã åŸã«ãå¿ èŠãªå Žæãšå¿ èŠã§ãªãå Žæã«æ°ããïŒm_bufferïŒãåã蟌ãããã«æ¥ããŸãã æéãçµã€ã«ã€ããŠãäž¡æ¹ãé»éè²ã«ãªããŸãã
ã¡ãœããã®æ¬è³ªã¯åçŽã§ã-ã¯ã©ã¹ãªããžã§ã¯ããæºåãããã¡ã¢ãªã«é 眮ããããšãå¯èœã§ãããå¿ èŠãªå Žåãããã€ãã®åçŽãªã«ãŒã«ãèŠããŠããã°ããããè¡ãã®ã¯æ¯èŒçç°¡åã§ãã
- ãªããžã§ã¯ããååšããéãã¡ã¢ãªã¯åžžã«ååšããå¿ èŠããããŸããã¡ã¢ãªãæ©æŠããããšããªããžã§ã¯ãã¯å£ããã¡ã¢ãªã»ã°ã¡ã³ããåç §ãå§ããŸãã
- ãã¹ãnewã«ãã£ãŠå²ãåœãŠããããªããžã§ã¯ãã®ã¯ã©ã¹ãã¹ãã©ã¯ã¿ã¯æåã§åŒã³åºãå¿ èŠããããŸããããã¯æ²ããããšã§ãããdeleteã¯ã¡ã¢ãªããã€ã³ã¿ã§åŠçããŸããã
ä»ã®ãã¹ãŠã¯ãéçºè ã®æ£ç¢ºããšç¡éã®æ³ååã«ãã£ãŠã®ã¿å¶éãããŸãã ããã¯ããªãã§ãã
Hacker MagazineïŒ190ã§æåã«çºè¡ãããŸããã
æçš¿è ïŒVladimir Qualab Kerimov ããªãŒãã£ã³ã°C ++éçºè ãParallels
ããã«ãŒã賌èªãã