-
Notifications
You must be signed in to change notification settings - Fork 1
/
Shared.cpp
98 lines (67 loc) · 2.21 KB
/
Shared.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
#include<tuple>
#include<functional>
#include<type_traits>
#include <cstring>
#include <cassert>
*/
#include<type_traits>
#include <atomic>
template<typename T>
class Shared{
public:
enum { valueSize = sizeof(T),valueAlign = alignof(T) };
using cType = unsigned int;
using aType = std::atomic<unsigned int>;
using aligned_t = typename std::aligned_storage<valueSize+sizeof(aType),valueAlign>::type;
Shared(){}
explicit Shared(Shared & rh) : m_ptr(rh.m_ptr) { incr();}
Shared(Shared const & rh) : m_ptr(rh.m_ptr) { incr();}
Shared & operator=(Shared const & rh) { decr(); m_ptr=rh.m_ptr; incr(); return *this;}
Shared(Shared && rh) : m_ptr(rh.m_ptr) { rh.m_ptr=nullptr;}
Shared & operator=(Shared && rh) { decr(); m_ptr=rh.m_ptr; rh.m_ptr=nullptr; return *this; }
template<typename ... Args>
explicit Shared(Args&&... args) : m_ptr(new aligned_t()) {
new(m_ptr) T(args...); count().store(1,std::memory_order_release);;
}
~Shared(){ decr();}
operator bool() const { return m_ptr;}
T * operator->() { return ptr();}
T & operator *() { return *ptr();}
T const * operator->() const { return ptr();}
T const & operator *() const { return *ptr();}
cType use_count() const { return m_ptr ? count().load(std::memory_order_acquire): 0;}
bool unique() const { return m_ptr ? 1==count().load(std::memory_order_acquire): true;}
T * ptr() { return (T*)(m_ptr); }
T const * ptr() const { return (T const *)(m_ptr);}
private:
void destroy() {
ptr()->~T();
delete m_ptr; m_ptr=nullptr;
}
void decr() {
if(!m_ptr) return;
auto count().fetch_
--count(); if (0==count()) destroy();
}
void incr() {
if(m_ptr) ++count();
}
aType & count() const { char * p = (char *)const_cast< aligned_t *>(m_ptr); return *(aType *)(p+valueSize);}
aligned_t * m_ptr=nullptr;
};
#include<vector>
#include<string>
#include<iostream>
int main() {
using VS = std::vector<std::string>;
using Sh = Shared<VS>;
Sh a;
Sh b(1,"hi");
std::cout << b.use_count() << " " << (*b)[0] << std::endl;
Sh c(b);
std::cout << b.use_count() << " " << (*b)[0] << std::endl;
Sh d(std::move(c));
std::cout << b.use_count() << " " << (*b)[0] << std::endl;
return 0;
}