NCBI C++ ToolKit
ncbi_safe_static.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_safe_static.cpp 86668 2019-06-04 16:08:30Z sadyrovr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Aleksey Grichenko
27  *
28  * File Description:
29  * Static variables safety - create on demand, destroy on termination
30  *
31  * CSafeStaticGuard:: -- guarantee for CSafePtr<> and CSafeRef<>
32  * destruction and cleanup
33  *
34  */
35 
36 
37 #include <ncbi_pch.hpp>
39 #include <corelib/ncbistd.hpp>
40 #include <corelib/ncbithr.hpp>
41 #include <corelib/ncbimtx.hpp>
42 #include <corelib/error_codes.hpp>
43 #include <memory>
44 #include <assert.h>
45 
46 
47 #define NCBI_USE_ERRCODE_X Corelib_Static
48 
49 
51 
52 
54  : CSafeStaticLifeSpan(eLifeLevel_Default, span, adjust)
55 {
56 }
57 
59  : m_LifeLevel(level),
60  m_LifeSpan(int(span) + adjust)
61 {
62  if (span == eLifeSpan_Min) {
63  m_LifeSpan = int(span); // ignore adjustments
64  adjust = 0;
65  }
66  if (adjust >= 5000 || adjust <= -5000) {
68  << "CSafeStaticLifeSpan level adjustment out of range: "
69  << adjust);
70  }
71  _ASSERT(adjust > -5000 && adjust < 5000);
72 }
73 
74 
76 {
77  static CSafeStaticLifeSpan s_DefaultSpan(eLifeSpan_Min);
78  return s_DefaultSpan;
79 }
80 
81 
82 /////////////////////////////////////////////////////////////////////////////
83 //
84 // CSafeStaticPtr_Base::
85 //
86 
87 // Protective mutex and the owner thread ID to avoid
88 // multiple initializations and deadlocks
89 DEFINE_CLASS_STATIC_MUTEX(CSafeStaticPtr_Base::sm_ClassMutex);
90 
91 
93 {
94  static CAtomicCounter s_CreationOrder;
95  return int(s_CreationOrder.Add(1));
96 }
97 
98 
100 {
101  if ( x_IsStdStatic() ) {
102  x_Cleanup();
103  }
104 }
105 
106 
107 /////////////////////////////////////////////////////////////////////////////
108 //
109 // CSafeStaticGuard::
110 //
111 
112 // CSafeStaticGuard reference counter
114 
115 
116 // CSafeStaticGuard reference counter
117 // On MSWin threads are killed before destruction of static objects in DLLs, so in
118 // most cases this check is useless.
119 #if defined(NCBI_WIN32_THREADS)
121 #else
123 #endif
124 
125 
127 {
128  // Initialize the guard only once
129  if (sm_RefCount == 0) {
132  }
133 
134  sm_RefCount++;
135 }
136 
137 
139 {
140  sm_ChildThreadsCheck = false;
141 }
142 
143 
145 {
146  CMutexGuard guard(CSafeStaticPtr_Base::sm_ClassMutex);
147 
148  // AppMain level variables are always destroyed before default level ones
150 
153  }
154 }
155 
156 
158 
159 
160 
162 {
163  CMutexGuard guard(CSafeStaticPtr_Base::sm_ClassMutex);
164 
165  // Protect CSafeStaticGuard destruction
166  if ( sh_CleanupGuard ) {
168  sh_CleanupGuard = 0;
169  delete tmp;
170  }
171  // If this is not the last reference, then do not destroy stack
172  if (--sm_RefCount > 0) {
173  return;
174  }
175  assert(sm_RefCount == 0);
176 
177  if (sm_ChildThreadsCheck) {
178  if (const auto tc = CThread::GetThreadsCount()) {
179  string msg = "On static data destruction, child thread(s) still running: " + to_string(tc);
180  ERR_POST_X(1, Error << msg);
182  }
183  }
184 
187 }
188 
189 
191 {
192  if (!stack) return;
193 
194  for ( int pass = 0; pass < 3; ++pass ) {
195  // Call Cleanup() for all variables registered
196  TStack cur_Stack;
197  swap(cur_Stack, *stack);
198  guard.Release();
199  NON_CONST_ITERATE(TStack, it, cur_Stack) {
200  (*it)->x_Cleanup();
201  }
202  guard.Guard(CSafeStaticPtr_Base::sm_ClassMutex);
203  }
204 
205  delete stack;
206  stack = nullptr;
207 }
208 
209 
210 // Global guard - to prevent premature destruction by e.g. GNU compiler
211 // (it destroys all local static variables before any global one)
213 
214 
215 // Initialization of the guard
217 {
218  // Local static variable - to initialize the guard
219  // as soon as the function is called (global static
220  // variable may be still uninitialized at this moment)
221  static CSafeStaticGuard sl_CleanupGuard;
222  if ( !sh_CleanupGuard )
224  return &sl_CleanupGuard;
225 }
226 
227 
CAtomicCounter –.
Definition: ncbicntr.hpp:71
void Guard(resource_type &resource)
Manually force the guard to protect some other resource.
Definition: guard.hpp:175
void Release()
Manually force the resource to be released.
Definition: guard.hpp:166
CSafeStaticGuard::
static void Destroy(CSafeStaticLifeSpan::ELifeLevel level)
Explicitly destroy all on-demand variables up to a specified level.
static CSafeStaticGuard * x_Get(void)
static TStack *& x_GetStack(CSafeStaticLifeSpan::ELifeLevel level)
CSafeStaticGuard(void)
Check if already initialized.
static bool sm_ChildThreadsCheck
multiset< CSafeStaticPtr_Base *, CSafeStatic_Less > TStack
static void x_Cleanup(CMutexGuard &guard, TStack *&stack)
~CSafeStaticGuard(void)
Check reference count, and if it is zero, then destroy all registered variables.
static void DisableChildThreadsCheck()
Disable checking on child thread(s) running during destruction.
CSafeStaticLifeSpan::
static CSafeStaticLifeSpan & GetDefault(void)
Get default life span (set to eLifeSpan_Min).
ELifeSpan
Predefined life spans for the safe static objects.
@ eLifeSpan_Min
std static, not adjustable
CSafeStaticLifeSpan(ELifeSpan span, int adjust=0)
Constructs a life span object from basic level and adjustment.
ELifeLevel
Predefined life levels for the safe static objects.
@ eLifeLevel_AppMain
Destroyed in CNcbiApplication::AppMain, if possible.
static int x_GetCreationOrder(void)
bool x_IsStdStatic(void) const
Include a standard set of the NCBI C++ Toolkit most basic headers.
static char tmp[3200]
Definition: utf8.c:42
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
TValue Add(int delta) THROWS_NONE
Atomically add value (=delta), and return new counter value.
Definition: ncbicntr.hpp:278
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static unsigned int GetThreadsCount()
Get total amount of threads This amount does not contain main thread.
Definition: ncbithr.hpp:785
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Definition of all error codes used in corelib (xncbi.lib).
static CSafeStaticGuard * sh_CleanupGuard
static CSafeStaticGuard sg_CleanupGuard
DEFINE_CLASS_STATIC_MUTEX(CSafeStaticPtr_Base::sm_ClassMutex)
Static variables safety - create on demand, destroy on application termination.
Multi-threading – mutexes; rw-locks; semaphore.
Multi-threading – classes, functions, and features.
#define assert(x)
Definition: srv_diag.hpp:58
#define _ASSERT
Modified on Sun Jun 16 04:32:34 2024 by modify_doxy.py rev. 669887