Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: webrtc/system_wrappers/interface/static_instance.h

Issue 1413333002: system_wrappers: rename interface -> include (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebased again! Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/system_wrappers/interface/sort.h ('k') | webrtc/system_wrappers/interface/stl_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
12 #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
13
14 #include <assert.h>
15
16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17 #ifdef _WIN32
18 #include "webrtc/system_wrappers/interface/fix_interlocked_exchange_pointer_win. h"
19 #endif
20
21 namespace webrtc {
22
23 enum CountOperation {
24 kRelease,
25 kAddRef,
26 kAddRefNoCreate
27 };
28 enum CreateOperation {
29 kInstanceExists,
30 kCreate,
31 kDestroy
32 };
33
34 template <class T>
35 // Construct On First Use idiom. Avoids
36 // "static initialization order fiasco".
37 static T* GetStaticInstance(CountOperation count_operation) {
38 // TODO (hellner): use atomic wrapper instead.
39 static volatile long instance_count = 0;
40 static T* volatile instance = NULL;
41 CreateOperation state = kInstanceExists;
42 #ifndef _WIN32
43 // This memory is staticly allocated once. The application does not try to
44 // free this memory. This approach is taken to avoid issues with
45 // destruction order for statically allocated memory. The memory will be
46 // reclaimed by the OS and memory leak tools will not recognize memory
47 // reachable from statics leaked so no noise is added by doing this.
48 static CriticalSectionWrapper* crit_sect(
49 CriticalSectionWrapper::CreateCriticalSection());
50 CriticalSectionScoped lock(crit_sect);
51
52 if (count_operation ==
53 kAddRefNoCreate && instance_count == 0) {
54 return NULL;
55 }
56 if (count_operation ==
57 kAddRef ||
58 count_operation == kAddRefNoCreate) {
59 instance_count++;
60 if (instance_count == 1) {
61 state = kCreate;
62 }
63 } else {
64 instance_count--;
65 if (instance_count == 0) {
66 state = kDestroy;
67 }
68 }
69 if (state == kCreate) {
70 instance = T::CreateInstance();
71 } else if (state == kDestroy) {
72 T* old_instance = instance;
73 instance = NULL;
74 // The state will not change past this point. Release the critical
75 // section while deleting the object in case it would be blocking on
76 // access back to this object. (This is the case for the tracing class
77 // since the thread owned by the tracing class also traces).
78 // TODO(hellner): this is a bit out of place but here goes, de-couple
79 // thread implementation with trace implementation.
80 crit_sect->Leave();
81 if (old_instance) {
82 delete old_instance;
83 }
84 // Re-acquire the lock since the scoped critical section will release
85 // it.
86 crit_sect->Enter();
87 return NULL;
88 }
89 #else // _WIN32
90 if (count_operation ==
91 kAddRefNoCreate && instance_count == 0) {
92 return NULL;
93 }
94 if (count_operation == kAddRefNoCreate) {
95 if (1 == InterlockedIncrement(&instance_count)) {
96 // The instance has been destroyed by some other thread. Rollback.
97 InterlockedDecrement(&instance_count);
98 assert(false);
99 return NULL;
100 }
101 // Sanity to catch corrupt state.
102 if (instance == NULL) {
103 assert(false);
104 InterlockedDecrement(&instance_count);
105 return NULL;
106 }
107 } else if (count_operation == kAddRef) {
108 if (instance_count == 0) {
109 state = kCreate;
110 } else {
111 if (1 == InterlockedIncrement(&instance_count)) {
112 // InterlockedDecrement because reference count should not be
113 // updated just yet (that's done when the instance is created).
114 InterlockedDecrement(&instance_count);
115 state = kCreate;
116 }
117 }
118 } else {
119 int new_value = InterlockedDecrement(&instance_count);
120 if (new_value == 0) {
121 state = kDestroy;
122 }
123 }
124
125 if (state == kCreate) {
126 // Create instance and let whichever thread finishes first assign its
127 // local copy to the global instance. All other threads reclaim their
128 // local copy.
129 T* new_instance = T::CreateInstance();
130 if (1 == InterlockedIncrement(&instance_count)) {
131 InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&instance),
132 new_instance);
133 } else {
134 InterlockedDecrement(&instance_count);
135 if (new_instance) {
136 delete static_cast<T*>(new_instance);
137 }
138 }
139 } else if (state == kDestroy) {
140 T* old_value = static_cast<T*>(InterlockedExchangePointer(
141 reinterpret_cast<void * volatile*>(&instance), NULL));
142 if (old_value) {
143 delete static_cast<T*>(old_value);
144 }
145 return NULL;
146 }
147 #endif // #ifndef _WIN32
148 return instance;
149 }
150
151 } // namspace webrtc
152
153 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
OLDNEW
« no previous file with comments | « webrtc/system_wrappers/interface/sort.h ('k') | webrtc/system_wrappers/interface/stl_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698