]> git.cworth.org Git - apitrace/commitdiff
Solve some issues with multithreaded apps.
authorJosé Fonseca <jrfonseca@tungstengraphics.com>
Mon, 7 Jul 2008 04:09:31 +0000 (13:09 +0900)
committerJosé Fonseca <jrfonseca@tungstengraphics.com>
Mon, 7 Jul 2008 04:09:31 +0000 (13:09 +0900)
SConstruct
base.py
log.hpp
windows.py

index 52c6f321bbc2e0eace6913173bcd58a957014f55..193e45a17010a30c54a5fcb00283908a38d47cf9 100644 (file)
@@ -40,6 +40,7 @@ env.Append(CPPDEFINES = [
     '_CRT_SECURE_NO_DEPRECATE',
     '_CRT_NON_CONFORMING_SWPRINTFS',
     'WIN32_LEAN_AND_MEAN',
+    '_USRDLL',
 ])
 
 if env['debug']:
@@ -49,7 +50,7 @@ else:
 env['PDB'] = '${TARGET.base}.pdb'
 
 cflags = [
-    '/W3', # warning level
+    '/W4', # warning level
 ]
 if env['debug']:
     cflags += [
@@ -63,6 +64,7 @@ else:
       '/Oi', # enable intrinsic functions
       '/Os', # favor code space
     ]
+cflags += ['/MT']
 env.Append(CFLAGS = cflags)
 env.Append(CXXFLAGS = cflags)
 
diff --git a/base.py b/base.py
index dc0be29e0c7e6dec422a0a7cede012462613e570..ea0034200c47dbce729ce7836301ae8dd437d5bf 100644 (file)
--- a/base.py
+++ b/base.py
@@ -164,12 +164,10 @@ class Interface(Type):
 
     def wrap_impl(self):
         print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name)
-        print '    m_pLog = new Log("d3d8trace");'
         print '    m_pInstance = pInstance;'
         print '}'
         print
         print '%s::~%s() {' % (self.wrap_name(), self.wrap_name())
-        print "    delete m_pLog;"
         print '}'
         print
         for method in self.itermethods():
@@ -179,14 +177,14 @@ class Interface(Type):
             else:
                 print '    %s result;' % method.type
                 result = 'result = '
-            print '    m_pLog->BeginCall("%s");' % (self.name + '::' + method.name)
+            print '    g_pLog->BeginCall("%s");' % (self.name + '::' + method.name)
             print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args]))
+            print '    g_pLog->EndCall();'
             for type, name in method.args:
                 if type.isoutput():
                     type.wrap_instance(name)
             if method.type is not Void:
                 method.type.wrap_instance('result')
-            print '    m_pLog->EndCall();'
             if method.name == 'QueryInterface':
                 print '    if(*ppvObj == m_pInstance)'
                 print '        *ppvObj = this;'
diff --git a/log.hpp b/log.hpp
index 2982a9f918d747f537d3cbc640de05c7cf80fcf7..df2cdc4395cd6a15ab1a2710c4861f6a8eb6f4e1 100644 (file)
--- a/log.hpp
+++ b/log.hpp
 #ifndef _LOG_HPP_
 #define _LOG_HPP_
 
+#include <windows.h>
+#include <tchar.h>
 #include <stdio.h>
-#include <stdlib.h>
 
 
-class Log
+class File
 {
 public:
-    Log(const char *name) {
-        char fileName[_MAX_PATH];
-        _snprintf(fileName, _MAX_PATH, "%s.%u.xml", name, rand());
-        file = fopen(fileName, "wt");
-        Write("<?xml version='1.0' encoding='UTF-8'?>\n");
-        Write("<?xml-stylesheet type='text/xsl' href='d3dtrace.xsl'?>\n");
-        Write("<trace>\n");
+    File(const TCHAR *szName, const TCHAR *szExtension) {
+        m_hFile = INVALID_HANDLE_VALUE;
+        Open(szName, szExtension);
+    }
+    
+    ~File() {
+        Close();
+    }
+
+    void Open(const TCHAR *szName, const TCHAR *szExtension) {
+        Close();
+        
+        DWORD dwCounter = 0;
+        do {
+            if(dwCounter)
+                _sntprintf(szFileName, MAX_PATH, TEXT("%s.%u.%s"), szName, dwCounter, szExtension);
+            else
+                _sntprintf(szFileName, MAX_PATH, TEXT("%s.%s"), szName, szExtension);
+
+            m_hFile = CreateFile(szFileName,
+                                 GENERIC_WRITE,
+                                 FILE_SHARE_WRITE,
+                                 NULL,
+                                 CREATE_NEW,
+                                 FILE_ATTRIBUTE_NORMAL,
+                                 NULL);
+            ++dwCounter;
+        } while(m_hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS);
+    }
+    
+    void ReOpen(void) {
+        Close();
+        
+        m_hFile = CreateFile(szFileName,
+                             GENERIC_WRITE,
+                             0,
+                             NULL,
+                             OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL,
+                             NULL);
+    }
+    
+    void Close(void) {
+        if(m_hFile != INVALID_HANDLE_VALUE) {
+            CloseHandle(m_hFile);
+            m_hFile = INVALID_HANDLE_VALUE;
+        }
+    }
+    
+    void Write(const char *szText) {
+        if(m_hFile == INVALID_HANDLE_VALUE)
+            return;
+        
+        DWORD dwBytesToWrite = (DWORD)strlen(szText);
+        DWORD dwBytesWritten = 0;
+        
+        while (dwBytesWritten < dwBytesToWrite) {
+            OVERLAPPED overlapped;
+            memset(&overlapped, 0, sizeof(OVERLAPPED));
+
+            /* Write to end of file */
+            overlapped.Offset = 0xffffffff;
+            overlapped.OffsetHigh = 0xffffffff;
+            
+            if(WriteFile(m_hFile,
+                         szText + dwBytesWritten,
+                         dwBytesToWrite - dwBytesWritten,
+                         &dwBytesWritten,
+                         &overlapped) == FALSE) {
+                Close();
+                Open(TEXT("extra"), TEXT("xml"));
+                return;
+            }
+        }
+    }
+    
+private:
+    HANDLE m_hFile;
+    TCHAR szFileName[MAX_PATH];
+};
+
+
+class Log : public File
+{
+public:
+    Log(const TCHAR *szName) : File(szName, TEXT("xml")) {
+        Write("<?xml version='1.0' encoding='UTF-8'?>");
+        NewLine();
+        Write("<?xml-stylesheet type='text/xsl' href='d3dtrace.xsl'?>");
+        NewLine();
+        Write("<trace>");
+        NewLine();
     }
     
     ~Log() {
-        Write("</trace>\n");
-        fclose(file);
+        Write("</trace>");
+        NewLine();
     }
     
     void NewLine(void) {
-        Write("\n");
+        Write("\r\n");
     }
     
     void Tag(const char *name) {
@@ -77,10 +163,12 @@ public:
     }
     
     void TextF(const char *format, ...) {
+        char szBuffer[4196];
         va_list ap;
         va_start(ap, format);
-        vfprintf(file, format, ap);
+        vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
         va_end(ap);
+        Escape(szBuffer);
     }
     
     void BeginCall(const char *function) {
@@ -105,7 +193,7 @@ public:
         NewLine();
     }
     
-    void BeginReturn(const char *type, const char *name) {
+    void BeginReturn(const char *type) {
         Write("\t\t");
         BeginTag("return", "type", type);
     }
@@ -120,20 +208,6 @@ protected:
         /* FIXME */
         Write(s);
     }
-    
-    void Write(const char *s) {
-        fputs(s, file);
-    }
-    
-    void WriteF(const char *f, ...) {
-        va_list ap;
-        va_start(ap, f);
-        vfprintf(file, f, ap);
-        va_end(ap);
-    }
-
-private:
-    FILE *file;
 };
 
 
index 8c7e3a018605c9e4ee1595a987add07320c444ad..8e8adee903dc651178ca7f6d8d89f653760952e9 100644 (file)
@@ -71,40 +71,50 @@ class Dll:
         pass
 
     def wrap_decl(self):
-        print '#pragma data_seg (".%s_shared")' % self.name
         print 'static HINSTANCE g_hDll = NULL;'
         print 'static Log * g_pLog = NULL;'
-        print '#pragma data_seg ()'
+        print 'static TCHAR g_szDll[MAX_PATH] = {0};'
         print
         print 'BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);'
         print
 
     def wrap_impl(self):
         print r'BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {'
-        print r'    TCHAR fileName[MAX_PATH];'
+        #print r'    Log * pLog;'
         print r'    switch(fdwReason) {'
         print r'    case DLL_PROCESS_ATTACH:'
-        print r'        if(!GetSystemDirectory(fileName, MAX_PATH))'
+        print r'        if(!GetSystemDirectory(g_szDll, MAX_PATH))'
         print r'            return FALSE;'
-        print r'        _tcscat(fileName, TEXT("\\%s.dll"));' % self.name
-        print r'        if(!g_hDll)'
-        print r'            g_hDll = LoadLibrary(fileName);'
-        print r'        if(!g_hDll)'
-        print r'            return FALSE;'
-        print r'        if(!g_pLog)'
-        print r'            g_pLog = new Log("%s");' % self.name
+        print r'        _tcscat(g_szDll, TEXT("\\%s.dll"));' % self.name
+        #print r'        if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)' 
+        #print r'            return FALSE;' 
+        #print r'        if(!g_pLog)'
+        #print r'            g_pLog = new Log(TEXT("%s"));' % self.name
+        print r'    case DLL_THREAD_ATTACH:'
+        #print r'        pLog = new Log(TEXT("%s"));' % self.name
+        #print r'        TlsSetValue(dwTlsIndex, pLog);'
+        print r'        return TRUE;'
+        print r'    case DLL_THREAD_DETACH:'
+        #print r'        pLog = (Log *)TlsGetValue(dwTlsIndex);' 
+        #print r'        if (pLog != NULL)'
+        #print r'            delete pLog;'
         print r'        return TRUE;'
         print r'    case DLL_PROCESS_DETACH:'
-        print r'        if(g_pLog)'
+        #print r'        pLog = (Log *)TlsGetValue(dwTlsIndex);' 
+        #print r'        if (pLog != NULL)'
+        #print r'            delete pLog;'
+        #print r'        TlsFree(dwTlsIndex);' 
+        print r'        if(g_pLog) {'
         print r'            delete g_pLog;'
-        print r'        if(g_hDll)'
+        print r'            g_pLog = NULL;'
+        print r'        }'
+        print r'        if(g_hDll) {'
         print r'            FreeLibrary(g_hDll);'
-        print r'        return TRUE;'
-        print r'    case DLL_THREAD_ATTACH:'
-        print r'        return TRUE;'
-        print r'    case DLL_THREAD_DETACH:'
+        print r'            g_hDll = NULL;'
+        print r'        }'
         print r'        return TRUE;'
         print r'    }'
+        print r'    (void)hinstDLL;'
         print r'    (void)lpvReserved;'
         print r'    return TRUE;'
         print r'}'
@@ -112,6 +122,11 @@ class Dll:
         for function in self.functions:
             type = 'P' + function.name
             print function.prototype() + ' {'
+            if 1:
+                print '    if(g_pLog)'
+                print '        delete g_pLog;'
+                print '    g_pLog = new Log(TEXT("%s"));' % self.name
+            #print '    g_pLog->ReOpen();'
             print '    typedef ' + function.prototype('* %s' % type) + ';'
             print '    %s pFunction;' % type
             if function.type is Void:
@@ -119,17 +134,22 @@ class Dll:
             else:
                 print '    %s result;' % function.type
                 result = 'result = '
+            print '        if(!g_hDll) {'
+            print '            g_hDll = LoadLibrary(g_szDll);'
+            print '            if(!g_hDll)'
+            print '                ExitProcess(0);'
+            print '        }'
             print '    pFunction = (%s)GetProcAddress( g_hDll, "%s");' % (type, function.name)
             print '    if(!pFunction)'
             print '        ExitProcess(0);'
             print '    g_pLog->BeginCall("%s");' % (function.name)
             print '    %spFunction(%s);' % (result, ', '.join([str(name) for type, name in function.args]))
+            print '    g_pLog->EndCall();'
             for type, name in function.args:
                 if type.isoutput():
                     type.wrap_instance(name)
             if function.type is not Void:
                 function.type.wrap_instance('result')
-            print '    g_pLog->EndCall();'
             if function.type is not Void:
                 print '    return result;'
             print '}'