6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
9
+ #include < __utility/no_destroy.h>
9
10
#include < algorithm>
10
11
#include < clocale>
11
12
#include < codecvt>
@@ -81,9 +82,8 @@ locale_t __cloc() {
81
82
82
83
namespace {
83
84
84
- struct release
85
- {
86
- void operator ()(locale::facet* p) {p->__release_shared ();}
85
+ struct releaser {
86
+ void operator ()(locale::facet* p) { p->__release_shared (); }
87
87
};
88
88
89
89
template <class T , class ...Args>
@@ -155,7 +155,11 @@ class _LIBCPP_HIDDEN locale::__imp
155
155
{return static_cast <size_t >(id) < facets_.size () && facets_[static_cast <size_t >(id)];}
156
156
const locale::facet* use_facet (long id) const ;
157
157
158
- private:
158
+ void acquire ();
159
+ void release ();
160
+ static __no_destroy<__imp> classic_locale_imp_;
161
+
162
+ private:
159
163
void install (facet* f, long id);
160
164
template <class F > void install (F* f) {install (f, f->id .__get ());}
161
165
template <class F > void install_from (const __imp& other);
@@ -500,7 +504,7 @@ locale::__imp::__imp(const __imp& other, facet* f, long id)
500
504
name_ (" *" )
501
505
{
502
506
f->__add_shared ();
503
- unique_ptr<facet, release > hold (f);
507
+ unique_ptr<facet, releaser > hold (f);
504
508
facets_ = other.facets_ ;
505
509
for (unsigned i = 0 ; i < other.facets_ .size (); ++i)
506
510
if (facets_[i])
519
523
locale::__imp::install (facet* f, long id)
520
524
{
521
525
f->__add_shared ();
522
- unique_ptr<facet, release > hold (f);
526
+ unique_ptr<facet, releaser > hold (f);
523
527
if (static_cast <size_t >(id) >= facets_.size ())
524
528
facets_.resize (static_cast <size_t >(id+1 ));
525
529
if (facets_[static_cast <size_t >(id)])
@@ -537,89 +541,78 @@ locale::__imp::use_facet(long id) const
537
541
538
542
// locale
539
543
540
- // This class basically implements __attribute__((no_destroy)), which isn't supported
541
- // by GCC as of writing this.
542
- template <class T >
543
- struct __no_destroy {
544
- template <class ... Args>
545
- explicit __no_destroy (Args&&... args) {
546
- T* obj = reinterpret_cast <T*>(&buf);
547
- new (obj) T (std::forward<Args>(args)...);
548
- }
549
-
550
- T& get () { return *reinterpret_cast <T*>(&buf); }
551
- T const & get () const { return *reinterpret_cast <T const *>(&buf); }
552
-
553
- private:
554
- alignas (T) byte buf[sizeof (T)];
555
- };
544
+ // We don't do reference counting on the classic locale.
545
+ // It's never destroyed anyway, but atomic reference counting may be very
546
+ // expensive in parallel applications. The classic locale is used by default
547
+ // in all streams. Note: if a new global locale is installed, then we lose
548
+ // the benefit of no reference counting.
549
+ __no_destroy<locale::__imp> locale::__imp::classic_locale_imp_ (__uninitialized_tag{}); // initialized below in classic()
556
550
557
551
const locale& locale::classic () {
558
- static const __no_destroy<locale> c (__private_tag{}, &make<__imp>(1u ));
559
- return c.get ();
552
+ static const __no_destroy<locale> classic_locale (__private_tag{}, [] {
553
+ // executed exactly once on first initialization of `classic_locale`
554
+ locale::__imp::classic_locale_imp_.__emplace (1u );
555
+ return &locale::__imp::classic_locale_imp_.__get ();
556
+ }());
557
+ return classic_locale.__get ();
560
558
}
561
559
562
560
locale& locale::__global () {
563
- static __no_destroy<locale> g (locale::classic ());
564
- return g.get ();
561
+ static __no_destroy<locale> g (locale::classic ());
562
+ return g.__get ();
565
563
}
566
564
567
- locale::locale () noexcept
568
- : __locale_ (__global ().__locale_ )
569
- {
570
- __locale_->__add_shared ();
565
+ void locale::__imp::acquire () {
566
+ if (this != &locale::__imp::classic_locale_imp_.__get ())
567
+ __add_shared ();
571
568
}
572
569
573
- locale::locale (const locale& l) noexcept
574
- : __locale_ (l.__locale_ )
575
- {
576
- __locale_->__add_shared ();
570
+ void locale::__imp::release () {
571
+ if (this != &locale::__imp::classic_locale_imp_.__get ())
572
+ __release_shared ();
577
573
}
578
574
579
- locale::~locale ()
580
- {
581
- __locale_->__release_shared ();
582
- }
575
+ locale::locale () noexcept : __locale_ (__global ().__locale_ ) { __locale_->acquire (); }
576
+
577
+ locale::locale (const locale& l) noexcept : __locale_ (l.__locale_ ) { __locale_->acquire (); }
578
+
579
+ locale::~locale () { __locale_->release (); }
583
580
584
581
const locale&
585
582
locale::operator =(const locale& other) noexcept
586
583
{
587
- other.__locale_ ->__add_shared ();
588
- __locale_->__release_shared ();
589
- __locale_ = other.__locale_ ;
590
- return *this ;
584
+ other.__locale_ ->acquire ();
585
+ __locale_->release ();
586
+ __locale_ = other.__locale_ ;
587
+ return *this ;
591
588
}
592
589
593
590
locale::locale (const char * name)
594
591
: __locale_ (name ? new __imp (name)
595
592
: (__throw_runtime_error (" locale constructed with null" ), nullptr ))
596
593
{
597
- __locale_->__add_shared ();
594
+ __locale_->acquire ();
598
595
}
599
596
600
- locale::locale (const string& name)
601
- : __locale_ (new __imp (name))
602
- {
603
- __locale_->__add_shared ();
604
- }
597
+ locale::locale (const string& name) : __locale_ (new __imp (name)) { __locale_->acquire (); }
605
598
606
599
locale::locale (const locale& other, const char * name, category c)
607
600
: __locale_ (name ? new __imp (*other.__locale_ , name, c)
608
601
: (__throw_runtime_error (" locale constructed with null" ), nullptr ))
609
602
{
610
- __locale_->__add_shared ();
603
+ __locale_->acquire ();
611
604
}
612
605
613
606
locale::locale (const locale& other, const string& name, category c)
614
607
: __locale_ (new __imp (*other.__locale_ , name, c))
615
608
{
616
- __locale_->__add_shared ();
609
+ __locale_->acquire ();
617
610
}
618
611
619
612
locale::locale (const locale& other, const locale& one, category c)
620
613
: __locale_ (new __imp (*other.__locale_ , *one.__locale_ , c))
621
614
{
622
- __locale_->__add_shared ();
615
+ __locale_->acquire ();
623
616
}
624
617
625
618
string
@@ -635,7 +628,7 @@ locale::__install_ctor(const locale& other, facet* f, long id)
635
628
__locale_ = new __imp (*other.__locale_ , f, id);
636
629
else
637
630
__locale_ = other.__locale_ ;
638
- __locale_->__add_shared ();
631
+ __locale_->acquire ();
639
632
}
640
633
641
634
locale
0 commit comments