DCL 4.0
Loading...
Searching...
No Matches
LibMain.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <stdlib.h> // malloc, free
4#if __DCL_PTHREAD
5#include <pthread.h> // pthread_mutex_lock, pthread_mutex_unlock
6#elif __DCL_WINDOWS
7#include <windows.h> // InterlockedIncrement, InterlockedDecrement
8#endif
9
10#include <dcl/Object.h>
11#include <dcl/Exception.h>
12#include <dcl/Thread.h>
13#include <dcl/StringWriter.h>
14#include "LibState.h"
15
16#if __DCL_HAVE_ALLOC_DEBUG
17#undef __DCL_ALLOC_LEVEL
18#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
19#endif
20
21#undef __THIS_FILE__
22static const char_t __THIS_FILE__[] = __T("dcl/LibMain.cpp");
23
24//#undef new
25#undef malloc
26#undef realloc
27#undef calloc
28#undef free
29
30__DCL_BEGIN_NAMESPACE
31
32#if __DCL_PTHREAD
33static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER;
34
35inline long __incrementAndGet(volatile long& _n)
36{
37 pthread_mutex_lock(&__mutex);
38 long n = ++_n;
39 pthread_mutex_unlock(&__mutex);
40 return n;
41}
42
43inline long __decrementAndGet(volatile long& _n)
44{
45 pthread_mutex_lock(&__mutex);
46 long n = --_n;
47 pthread_mutex_unlock(&__mutex);
48 return n;
49}
50#elif __DCL_WINDOWS
51inline long __incrementAndGet(volatile long& _n)
52{
53 return InterlockedIncrement(&_n);
54}
55
56inline long __decrementAndGet(volatile long& _n)
57{
58 return InterlockedDecrement(&_n);
59}
60#endif
61
63static long __initializeCount = 0;
64
65// Thread.cpp
67extern void __cleanupThreadEnvironment();
68
69static int __DCLInitialize()
70{
71 long initCount =__incrementAndGet(__initializeCount);
72#if __DCL_DEBUG
73 if (__pLibState) {
74 __DCL_TRACE1(__T("__DCLInitialize initCount [%d]\n"), initCount);
75 }
76#endif
77
78 if (initCount == 1) {
80
81#if __DCL_HAVE_ALLOC_DEBUG
82#undef new
83#endif
84 /*
85 __pLibState = new LibState();
86 Object.h에서 정의한 new가 호출되기 때문에 이것을 사용할 수 없다.
87 */
88 __pLibState = (LibState*) malloc(sizeof(LibState));
89 new((void*)__pLibState) LibState;
90
91#if __DCL_HAVE_ALLOC_DEBUG
92#define new __DCL_DEBUG_NEW
93#endif
94 }
95
96 return initCount;
97}
98
99static void __DCLCleanup()
100{
101 if (__decrementAndGet(__initializeCount) == 0) {
102 if (__pLibState->pfnSQLCleanup) {
103 __pLibState->pfnSQLCleanup();
104 __pLibState->pfnSQLCleanup = NULL;
105 }
106#ifndef __DCL_HAVE_ALLOC_DEBUG
107 // 2024-11-16
108 // regex에서
109 // 메모리 디버깅을 위한 DCL의 new, new[]이 호출 된다.
110 // 이들은 main을 빠져 나간 후, 프로세스 종료 직전에 컴파일러에에 의해
111 // delete가 호출된다.
112 // ALLOC_DEBUG 상태의 delete, delete[]가 사용될 수 있도록 남겨놓는다.
113 __pLibState->~LibState();
114 free(__pLibState);
116#endif
118 }
119}
120
121__DCL_END_NAMESPACE
122
123__DCL_USING_NAMESPACE
124
125#if __DCL_DEBUG
127
128static Writer* __pGlobalDebugOut = NULL;
129
130DCLCAPI __DCL_NAMESPACE Writer* DCLDebugSetGlobalReport(
131 __DCL_NAMESPACE Writer* pNewOut
132 )
133{
134 __pLibState->lockGlobalOutput.lock();
135 Writer* pOld = __pGlobalDebugOut;
136 __pGlobalDebugOut = pNewOut;
137 __pLibState->lockGlobalOutput.unlock();
138 return pOld;
139}
140
141DCLCAPI __DCL_NAMESPACE Writer* DCLDebugSetThreadReport(
142 unsigned long uThreadId,
143 __DCL_NAMESPACE Writer* pNewOut
144 )
145{
146 Writer* pOldOut = NULL;
147
148 __pLibState->lockThreadOutput.lock();
149
150 PtrHashMap::Node* pNode = __pLibState->mapThreadOutput.find((const void*)(size_t) uThreadId);
151 if (pNode) {
152 pOldOut = (Writer*)(pNode->value);
153 pNode->value = pNewOut;
154 }
155 else {
156 __pLibState->mapThreadOutput[(const void*)(size_t) uThreadId] = pNewOut;
157 }
158
159 __pLibState->lockThreadOutput.unlock();
160
161 return pOldOut;
162}
163
165
166DCLCAPI void DCLDebugAssert(
167 const char_t* _filename,
168 unsigned int _line,
169 const char_t* _expr,
170 const char_t* _message
172{
173 throw new AssertError(_filename, _line, _expr, _message);
174}
175
176
178
179DCLCAPI void DCLDebugTrace(
180 const char_t* _filename,
181 unsigned int _line,
182 const char_t* _format,
183 ...
184 )
185{
186 Writer* pOut = NULL;
187 __pLibState->lockThreadOutput.lock();
188 PtrHashMap::Node* pNode =
189 __pLibState->mapThreadOutput.find((const void*)(size_t) Thread::getCurrentThreadId());
190 if (pNode) {
191 pOut = (Writer*)(pNode->value);
192 }
193 __pLibState->lockThreadOutput.unlock();
194
195 if (!pOut) {
196 pOut = __pGlobalDebugOut;
197 }
198
199 if (pOut) {
200 // Writer::vprintf의 구현에 __DCL_TRACE 코드가 있으면 이 부분이 재귀적으로 호출된다.
201 StringWriter sw(256);
202 sw.printf(__T("%ls:%u "), _filename, _line);
203
204 va_list arglist;
205 va_start(arglist, _format);
206 sw.vprintf(_format, arglist);
207 va_end(arglist);
208
209 // __pLibState->lockGlobalOutput
210 // WIndows CriticalSection, pthread_mutex로 구현되어 있다.
211 // CriticalSection의 경우 단일 프로세스, 단일 스레드에서 Block되지 않는다.
212 // pthread_mutex는 단일 프로세스, 단일 스레데에서 Block된다.
213 if (pOut == __pGlobalDebugOut) {
214 __pLibState->lockGlobalOutput.lock();
215 }
216 try {
217 *pOut << sw.toString();
218 pOut->flush();
219 }
220 catch(IOException* e) {
221 *pOut << e->toStringAll() << endl;
222 e->destroy();
223 }
224 if (pOut == __pGlobalDebugOut) {
225 __pLibState->lockGlobalOutput.unlock();
226 }
227 }
228}
229
230#endif // __DCL_DEBUG
231
232#if __DCL_HAVE_MANUAL_INITIALIZE
233DCLCAPI int DCLInitialize()
234{
235 return __DCLInitialize();
236}
237
238DCLCAPI void DCLCleanup()
239{
240 __DCLCleanup();
241}
242#elif defined(__DCL_CORE_EXPORTS)
243// DSO Initialize
244#if __DCL_WINDOWS
245BOOL WINAPI DllMain(
246 HINSTANCE hinstDLL, // handle to DLL module
247 DWORD fdwReason, // reason for calling function
248 LPVOID lpReserved ) // reserved
249{
250 switch (fdwReason) {
251 case DLL_PROCESS_ATTACH:
252 __DCLInitialize();
253 break;
254 case DLL_PROCESS_DETACH:
255 __DCLCleanup();
256 break;
257 case DLL_THREAD_ATTACH:
258 __DCL_TRACE0(__T("DCLCored.dll DLL_THREAD_ATTACH\n"));
259 break;
260 case DLL_THREAD_DETACH:
261 __DCL_TRACE0(__T("DCLCored.dll DLL_THREAD_DETACH\n"));
262 break;
263 }
264 return TRUE;
265}
266#else
267__attribute__((constructor))
268void _DCL_init()
269{
270 __DCLInitialize();
271}
272
273__attribute__((destructor))
274void _DCL_fini()
275{
276 __DCLCleanup();
277}
278#endif
279
280#else
281
282// Static Library
283#ifdef _MSC_VER
284#pragma optimize ("", off)
285#endif
286
288{
289public:
291 {
292 __DCLInitialize();
293 }
295 {
296 __DCLCleanup();
297 }
298};
299
300static __LibInitializer __libInitializer;
301
302#ifdef _MSC_VER
303#pragma optimize ("", off)
304#endif
305
306#endif
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define DCLCAPI
Definition Config.h:100
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
int BOOL
#define TRUE
void __cleanupThreadEnvironment()
Definition Thread.cpp:324
__DCL_BEGIN_NAMESPACE LibState * __pLibState
Definition LibMain.cpp:62
void __initializeThreadEnvironment()
Definition Thread.cpp:316
#define __DCL_TRACE0(psz)
Definition Object.h:375
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __T(str)
Definition Object.h:44
#define endl
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
virtual String toString() const
Definition Object.cpp:187
static unsigned long getCurrentThreadId()
Definition Thread.cpp:173
const void * value
Definition LibState.h:149