Ik heb net de volgende class geschreven:
De eerste code is efficienter, maar heeft een probleem met de assignment operator=. Hier kan je volgens mij niet omheen, tenzij je een pointerwise kopie zou kunnen maken, en die dan in swappen. (copy-swap idiom)
De tweede lijkt me robuust onder elk geval, maar is wel redelijk traag denk ik. Waarschijnlijk te traag voor bv het locken van een variabele in een loop.
Is hier geen standaard object voor? Iets in boost misschien?
C++:
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
| // Cleanup functor oject must have a non-throwing assignment operator // The cleanup function must not throw (as this will cause an exception in dtor) template <typename Init, typename Cleanup> class Sentry { Cleanup clean_; bool owns_; public: Sentry() : owns_(false) {} // if either Cleanup's cctor throws or initialize() throws, all is well since cleanup is never called. Sentry(Init initialize, Cleanup c) : clean_(c), owns_(true) { initialize(); } ~Sentry() { if (owns_) clean_(); } // if cleanup's cctor throws all is well, we never take ownership. This might cause an object to be lost // but at least a proper exception notifies us in that case Sentry(Sentry& src) : clean_(src.clean_), owns_(src.owns_) { src.owns_ = false; } // this is not perfect...if (err assignment operator) throws...havoc const Sentry& operator=(Sentry& src) { if (owns_) clean_(); clean_ = src.clean_; // must not throw owns_ = true; src.owns_ = false; } }; // 2nd implementation, safe but slow? template <typename I, typename C> class Sentry2 { class X_ { C c_; public: X_(C c) : c_(c) {} ~X_() {c_();} }; std::auto_ptr<X_> xptr_; public: // if new throws, all is well, no functors called, no object created // problem with i(), if it throws, c() would be called, so catch a possible exception and remove our ownership Sentry2(I i, C c) : xptr_(new X_(c)) { try { i(); } catch (...) { xptr_.reset(); throw; } } ~Sentry2() {} }; // usage: typedef Sentry<boost::function<void ()>, boost::function<void ()> > DisableGuard; CGContext::DisableGuard CGContext::guardedEnable() { return CGContext::DisableGuard( boost::bind(&CGContext::enable, this), boost::bind(&CGContext::disable, this) ); } |
De eerste code is efficienter, maar heeft een probleem met de assignment operator=. Hier kan je volgens mij niet omheen, tenzij je een pointerwise kopie zou kunnen maken, en die dan in swappen. (copy-swap idiom)
De tweede lijkt me robuust onder elk geval, maar is wel redelijk traag denk ik. Waarschijnlijk te traag voor bv het locken van een variabele in een loop.
Is hier geen standaard object voor? Iets in boost misschien?
[ Voor 3% gewijzigd door Zoijar op 06-07-2005 12:36 ]