1. wxThread changes (detached/joinable) for MSW and docs updates
2. wxUSE_GUI=0 compilation for MSW (use vc6dll.t with tmake) and many small fixes related to this 3. an attempt to make wxLog more MT friendly 4. a small fix for wxRegConfig: it doesn't create empty unused keys any more (SetPath() would always create a key, now it's deleted if it was empty) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4712 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -239,7 +239,7 @@ iniconf.cpp M 16
|
||||
joystick.cpp M
|
||||
listbox.cpp M
|
||||
listctrl.cpp M 32
|
||||
main.cpp M
|
||||
main.cpp M B
|
||||
mdi.cpp M
|
||||
menu.cpp M
|
||||
menuitem.cpp M
|
||||
@@ -258,9 +258,9 @@ printdlg.cpp M
|
||||
printwin.cpp M
|
||||
radiobox.cpp M
|
||||
radiobut.cpp M
|
||||
regconf.cpp M 32
|
||||
regconf.cpp M 32,B
|
||||
region.cpp M
|
||||
registry.cpp M 32
|
||||
registry.cpp M 32,B
|
||||
scrolbar.cpp M
|
||||
settings.cpp M
|
||||
slider95.cpp M 32
|
||||
@@ -277,12 +277,12 @@ taskbar.cpp M 32
|
||||
tbar95.cpp M 32
|
||||
tbarmsw.cpp M 16
|
||||
textctrl.cpp M
|
||||
thread.cpp M 32
|
||||
thread.cpp M 32,B
|
||||
timer.cpp M
|
||||
tooltip.cpp M 32
|
||||
treectrl.cpp M 32
|
||||
utils.cpp M
|
||||
utilsexc.cpp M
|
||||
utils.cpp M B
|
||||
utilsexc.cpp M B
|
||||
uuid.cpp M O
|
||||
wave.cpp M
|
||||
window.cpp M
|
||||
@@ -292,7 +292,7 @@ gsocket.c M S
|
||||
dialup.cpp U
|
||||
fontenum.cpp U
|
||||
fontutil.cpp U
|
||||
threadpsx.cpp U
|
||||
threadpsx.cpp U B
|
||||
utilsunx.cpp U B
|
||||
gsocket.c U
|
||||
|
||||
|
@@ -81,7 +81,7 @@ RSC=rc.exe
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=1 /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
@@ -104,7 +104,7 @@ LIB32=link.exe -lib
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D wxUSE_GUI=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
|
145
distrib/msw/tmake/vc6base.t
Normal file
145
distrib/msw/tmake/vc6base.t
Normal file
@@ -0,0 +1,145 @@
|
||||
#!#############################################################################
|
||||
#! File: vc6base.t
|
||||
#! Purpose: tmake template file from which wxBase.dsp is generated by running
|
||||
#! tmake -t vc6base wxwin.pro -o wxBase.dsp
|
||||
#! Author: Vadim Zeitlin
|
||||
#! Created: 27.11.99
|
||||
#! Version: $Id$
|
||||
#!#############################################################################
|
||||
#${
|
||||
#! include the code which parses filelist.txt file and initializes
|
||||
#! %wxCommon, %wxGeneric and %wxMSW hashes.
|
||||
IncludeTemplate("filelist.t");
|
||||
|
||||
#! now transform these hashes into $project tags
|
||||
foreach $file (sort keys %wxCommon) {
|
||||
next if $wxCommon{$file} !~ /\bB\b/;
|
||||
|
||||
my $tag = $file =~ /\.c$/ ? "WXCSRCS" : "WXCOMMONSRCS";
|
||||
$project{$tag} .= $file . " "
|
||||
}
|
||||
|
||||
foreach $file (sort keys %wxMSW) {
|
||||
next if $wxMSW{$file} !~ /\bB\b/;
|
||||
|
||||
my $tag = $file =~ /\.c$/ ? "WXMSWCSRCS" : "WXMSWSRCS";
|
||||
$project{$tag} .= $file . " "
|
||||
}
|
||||
|
||||
foreach $file (sort keys %wxBase) {
|
||||
my $tag = $file =~ /\.c$/ ? "WXCSRCS" : "WXCOMMONSRCS";
|
||||
$project{$tag} .= $file . " "
|
||||
}
|
||||
#$}
|
||||
# Microsoft Developer Studio Project File - Name="wxBase" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=wxBase - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wxBase.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wxBase.mak" CFG="wxBase - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "wxBase - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wxBase - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "wxBase - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=0 /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "wxBase - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D wxUSE_GUI=0 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo /o"lib/wxBase.bsc"
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "wxBase - Win32 Release"
|
||||
# Name "wxBase - Win32 Debug"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\msw\dummy.cpp
|
||||
# ADD CPP /Yc"wx/wxprec.h"
|
||||
# End Source File
|
||||
#$ ExpandGlue("WXCOMMONSRCS", "# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# End Source File\n");
|
||||
#$ ExpandGlue("WXMSWSRCS", "# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# End Source File\n");
|
||||
#$ ExpandGlue("WXCSRCS", "# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n");
|
||||
#$ ExpandGlue("WXMSWCSRCS", "# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n");
|
||||
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\common\y_tab.c
|
||||
|
||||
!IF "$(CFG)" == "wxBase - Win32 Release"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "wxBase - Win32 Debug"
|
||||
|
||||
# ADD CPP /W1
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
@@ -83,7 +83,7 @@ RSC=rc.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W4 /GX /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD CPP /nologo /MT /W4 /GX /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=1 /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
@@ -109,7 +109,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W4 /Gm /ZI /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D "__WXDEBUG__" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W4 /Gm /ZI /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D "__WXDEBUG__" /D wxUSE_GUI=1 /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
|
@@ -282,7 +282,10 @@ protected:
|
||||
#include "wx/stubs/app.h"
|
||||
#endif
|
||||
#else // !GUI
|
||||
typedef wxAppBase wxApp;
|
||||
// can't use typedef because wxApp forward declared as a class
|
||||
class WXDLLEXPORT wxApp : public wxAppBase
|
||||
{
|
||||
};
|
||||
#endif // GUI/!GUI
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -322,13 +325,13 @@ inline void WXDLLEXPORT wxPostEvent(wxEvtHandler *dest, wxEvent& event)
|
||||
dest->AddPendingEvent(event);
|
||||
}
|
||||
|
||||
#endif // wxUSE_GUI/!wxUSE_GUI
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
// console applications may avoid using DECLARE_APP and IMPLEMENT_APP macros
|
||||
// and call these functions instead at the program startup and termination
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_NOGUI
|
||||
#if !wxUSE_GUI
|
||||
|
||||
// initialize the library (may be called as many times as needed, but each
|
||||
// call to wxInitialize() must be matched by wxUninitialize())
|
||||
@@ -338,7 +341,7 @@ extern bool WXDLLEXPORT wxInitialize();
|
||||
// wxUninitialize()
|
||||
extern void WXDLLEXPORT wxUninitialize();
|
||||
|
||||
#endif // wxUSE_NOGUI
|
||||
#endif // !wxUSE_GUI
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// macros for dynamic creation of the application object
|
||||
|
@@ -43,6 +43,8 @@ static const double pt2mm = (1/(METRIC_CONVERSION_CONSTANT*72));
|
||||
// standard icons from the resources
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_GUI
|
||||
|
||||
WXDLLEXPORT_DATA(extern HICON) wxSTD_FRAME_ICON;
|
||||
WXDLLEXPORT_DATA(extern HICON) wxSTD_MDIPARENTFRAME_ICON;
|
||||
WXDLLEXPORT_DATA(extern HICON) wxSTD_MDICHILDFRAME_ICON;
|
||||
@@ -51,6 +53,8 @@ WXDLLEXPORT_DATA(extern HICON) wxDEFAULT_MDIPARENTFRAME_ICON;
|
||||
WXDLLEXPORT_DATA(extern HICON) wxDEFAULT_MDICHILDFRAME_ICON;
|
||||
WXDLLEXPORT_DATA(extern HFONT) wxSTATUS_LINE_FONT;
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// define things missing from some compilers' headers
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -268,9 +272,13 @@ private:
|
||||
// global data
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if 0 // where is this??
|
||||
// The MakeProcInstance version of the function wxSubclassedGenericControlProc
|
||||
WXDLLEXPORT_DATA(extern FARPROC) wxGenericControlSubClassProc;
|
||||
#endif // 0
|
||||
|
||||
WXDLLEXPORT_DATA(extern wxChar*) wxBuffer;
|
||||
|
||||
WXDLLEXPORT_DATA(extern HINSTANCE) wxhInstance;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -279,11 +287,13 @@ WXDLLEXPORT_DATA(extern HINSTANCE) wxhInstance;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
WXDLLEXPORT HINSTANCE wxGetInstance();
|
||||
WXDLLEXPORT HINSTANCE wxGetInstance();
|
||||
}
|
||||
|
||||
WXDLLEXPORT void wxSetInstance(HINSTANCE hInst);
|
||||
|
||||
#if wxUSE_GUI
|
||||
|
||||
WXDLLEXPORT wxWindow* wxFindWinFromHandle(WXHWND hWnd);
|
||||
|
||||
WXDLLEXPORT void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font);
|
||||
@@ -316,5 +326,7 @@ inline bool wxStyleHasBorder(long style)
|
||||
wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
|
||||
}
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#endif
|
||||
// _WX_PRIVATE_H_
|
||||
|
@@ -187,6 +187,19 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
// FindResource
|
||||
#ifdef FindResource
|
||||
#undef FindResource
|
||||
inline HRSRC FindResource(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
return FindResourceW(hModule, lpName, lpType);
|
||||
#else
|
||||
return FindResourceA(hModule, lpName, lpType);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// IsMaximized
|
||||
|
||||
#ifdef IsMaximized
|
||||
|
@@ -53,9 +53,16 @@ enum wxThreadError
|
||||
wxTHREAD_NO_RESOURCE, // No resource left to create a new thread
|
||||
wxTHREAD_RUNNING, // The thread is already running
|
||||
wxTHREAD_NOT_RUNNING, // The thread isn't running
|
||||
wxTHREAD_KILLED, // Thread we waited for had to be killed
|
||||
wxTHREAD_MISC_ERROR // Some other error
|
||||
};
|
||||
|
||||
enum wxThreadKind
|
||||
{
|
||||
wxTHREAD_DETACHED,
|
||||
wxTHREAD_JOINABLE
|
||||
};
|
||||
|
||||
// defines the interval of priority
|
||||
enum
|
||||
{
|
||||
@@ -231,15 +238,18 @@ private:
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Thread management class
|
||||
// Thread class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// FIXME Thread termination model is still unclear. Delete() should probably
|
||||
// have a timeout after which the thread must be Kill()ed.
|
||||
// there are two different kinds of threads: joinable and detached (default)
|
||||
// ones. Only joinable threads can return a return code and only detached
|
||||
// threads auto-delete themselves - the user should delete the joinable
|
||||
// threads manually.
|
||||
|
||||
// NB: in the function descriptions the words "this thread" mean the thread
|
||||
// created by the wxThread object while "main thread" is the thread created
|
||||
// during the process initialization (a.k.a. the GUI thread)
|
||||
|
||||
class wxThreadInternal;
|
||||
class WXDLLEXPORT wxThread
|
||||
{
|
||||
@@ -266,34 +276,52 @@ public:
|
||||
// NB: at least under MSW worker threads can not call ::wxSleep()!
|
||||
static void Sleep(unsigned long milliseconds);
|
||||
|
||||
// default constructor
|
||||
wxThread();
|
||||
// constructor only creates the C++ thread object and doesn't create (or
|
||||
// start) the real thread
|
||||
wxThread(wxThreadKind kind = wxTHREAD_DETACHED);
|
||||
|
||||
// functions that change the thread state: all these can only be called
|
||||
// from _another_ thread (typically the thread that created this one, e.g.
|
||||
// the main thread), not from the thread itself
|
||||
|
||||
// function that change the thread state
|
||||
// create a new thread - call Run() to start it
|
||||
wxThreadError Create();
|
||||
|
||||
// starts execution of the thread - from the moment Run() is called the
|
||||
// execution of wxThread::Entry() may start at any moment, caller
|
||||
// starts execution of the thread - from the moment Run() is called
|
||||
// the execution of wxThread::Entry() may start at any moment, caller
|
||||
// shouldn't suppose that it starts after (or before) Run() returns.
|
||||
wxThreadError Run();
|
||||
|
||||
// stops the thread if it's running and deletes the wxThread object
|
||||
// freeing its memory. This function should also be called if the
|
||||
// Create() or Run() fails to free memory (otherwise it will be done by
|
||||
// the thread itself when it terminates). The return value is the
|
||||
// thread exit code if the thread was gracefully terminated, 0 if it
|
||||
// wasn't running and -1 if an error occured.
|
||||
ExitCode Delete();
|
||||
// stops the thread if it's running and deletes the wxThread object if
|
||||
// this is a detached thread freeing its memory - otherwise (for
|
||||
// joinable threads) you still need to delete wxThread object
|
||||
// yourself.
|
||||
//
|
||||
// this function only works if the thread calls TestDestroy()
|
||||
// periodically - the thread will only be deleted the next time it
|
||||
// does it!
|
||||
//
|
||||
// will fill the rc pointer with the thread exit code if it's !NULL
|
||||
wxThreadError Delete(ExitCode *rc = (ExitCode *)NULL);
|
||||
|
||||
// waits for a joinable thread to finish and returns its exit code
|
||||
//
|
||||
// Returns (ExitCode)-1 on error (for example, if the thread is not
|
||||
// joinable)
|
||||
ExitCode Wait();
|
||||
|
||||
// kills the thread without giving it any chance to clean up - should
|
||||
// not be used in normal circumstances, use Delete() instead. It is a
|
||||
// dangerous function that should only be used in the most extreme
|
||||
// cases! The wxThread object is deleted by Kill() if thread was
|
||||
// killed (i.e. no errors occured).
|
||||
// cases!
|
||||
//
|
||||
// The wxThread object is deleted by Kill() if the thread is
|
||||
// detachable, but you still have to delete it manually for joinable
|
||||
// threads.
|
||||
wxThreadError Kill();
|
||||
|
||||
// pause a running thread
|
||||
// pause a running thread: as Delete(), this only works if the thread
|
||||
// calls TestDestroy() regularly
|
||||
wxThreadError Pause();
|
||||
|
||||
// resume a paused thread
|
||||
@@ -308,10 +336,6 @@ public:
|
||||
// Get the current priority.
|
||||
unsigned int GetPriority() const;
|
||||
|
||||
// Get the thread ID - a platform dependent number which uniquely
|
||||
// identifies a thread inside a process
|
||||
unsigned long GetID() const;
|
||||
|
||||
// thread status inquiries
|
||||
// Returns true if the thread is alive: i.e. running or suspended
|
||||
bool IsAlive() const;
|
||||
@@ -320,11 +344,22 @@ public:
|
||||
// Returns true if the thread is suspended
|
||||
bool IsPaused() const;
|
||||
|
||||
// is the thread of detached kind?
|
||||
bool IsDetached() const { return m_isDetached; }
|
||||
|
||||
// Get the thread ID - a platform dependent number which uniquely
|
||||
// identifies a thread inside a process
|
||||
unsigned long GetId() const;
|
||||
|
||||
// called when the thread exits - in the context of this thread
|
||||
//
|
||||
// NB: this function will not be called if the thread is Kill()ed
|
||||
virtual void OnExit() { }
|
||||
|
||||
// dtor is public, but the detached threads should never be deleted - use
|
||||
// Delete() instead (or leave the thread terminate by itself)
|
||||
virtual ~wxThread();
|
||||
|
||||
protected:
|
||||
// Returns TRUE if the thread was asked to terminate: this function should
|
||||
// be called by the thread from time to time, otherwise the main thread
|
||||
@@ -332,14 +367,7 @@ protected:
|
||||
bool TestDestroy();
|
||||
|
||||
// exits from the current thread - can be called only from this thread
|
||||
void Exit(void *exitcode = 0);
|
||||
|
||||
// destructor is private - user code can't delete thread objects, they will
|
||||
// auto-delete themselves (and thus must be always allocated on the heap).
|
||||
// Use Delete() or Kill() instead.
|
||||
//
|
||||
// NB: derived classes dtors shouldn't be public neither!
|
||||
virtual ~wxThread();
|
||||
void Exit(ExitCode exitcode = 0);
|
||||
|
||||
// entry point for the thread - called by Run() and executes in the context
|
||||
// of this thread.
|
||||
@@ -357,6 +385,9 @@ private:
|
||||
|
||||
// protects access to any methods of wxThreadInternal object
|
||||
wxCriticalSection m_critsect;
|
||||
|
||||
// true if the thread is detached, false if it is joinable
|
||||
bool m_isDetached;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -369,9 +400,9 @@ void WXDLLEXPORT wxMutexGuiLeave();
|
||||
|
||||
// macros for entering/leaving critical sections which may be used without
|
||||
// having to take them inside "#if wxUSE_THREADS"
|
||||
#define wxENTER_CRIT_SECT(cs) (cs)->Enter()
|
||||
#define wxLEAVE_CRIT_SECT(cs) (cs)->Leave()
|
||||
#define wxCRIT_SECT_LOCKER(name, cs) wxCriticalSectionLocker name(*cs)
|
||||
#define wxENTER_CRIT_SECT(cs) (cs).Enter()
|
||||
#define wxLEAVE_CRIT_SECT(cs) (cs).Leave()
|
||||
#define wxCRIT_SECT_LOCKER(name, cs) wxCriticalSectionLocker name(cs)
|
||||
|
||||
#else // !wxUSE_THREADS
|
||||
|
||||
|
@@ -172,7 +172,7 @@ WXDLLEXPORT int wxKill(long pid, wxSignal sig = wxSIGTERM);
|
||||
// If no command then just the shell
|
||||
WXDLLEXPORT bool wxShell(const wxString& command = wxEmptyString);
|
||||
|
||||
// Sleep for nSecs seconds under UNIX, do nothing under Windows
|
||||
// Sleep for nSecs seconds
|
||||
WXDLLEXPORT void wxSleep(int nSecs);
|
||||
|
||||
// Sleep for a given amount of milliseconds
|
||||
|
@@ -30,8 +30,8 @@
|
||||
// what to test?
|
||||
|
||||
//#define TEST_ARRAYS
|
||||
#define TEST_LOG
|
||||
//#define TEST_THREADS
|
||||
//#define TEST_LOG
|
||||
#define TEST_THREADS
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
@@ -47,30 +47,51 @@
|
||||
|
||||
static size_t gs_counter = (size_t)-1;
|
||||
static wxCriticalSection gs_critsect;
|
||||
static wxCondition gs_cond;
|
||||
|
||||
class MyThread : public wxThread
|
||||
class MyJoinableThread : public wxThread
|
||||
{
|
||||
public:
|
||||
MyThread(char ch);
|
||||
MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
|
||||
{ m_n = n; Create(); }
|
||||
|
||||
// thread execution starts here
|
||||
virtual void *Entry();
|
||||
virtual ExitCode Entry();
|
||||
|
||||
private:
|
||||
size_t m_n;
|
||||
};
|
||||
|
||||
wxThread::ExitCode MyJoinableThread::Entry()
|
||||
{
|
||||
unsigned long res = 1;
|
||||
for ( size_t n = 1; n < m_n; n++ )
|
||||
{
|
||||
res *= n;
|
||||
|
||||
// it's a loooong calculation :-)
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
return (ExitCode)res;
|
||||
}
|
||||
|
||||
class MyDetachedThread : public wxThread
|
||||
{
|
||||
public:
|
||||
MyDetachedThread(char ch) { m_ch = ch; Create(); }
|
||||
|
||||
// thread execution starts here
|
||||
virtual ExitCode Entry();
|
||||
|
||||
// and stops here
|
||||
virtual void OnExit();
|
||||
|
||||
public:
|
||||
private:
|
||||
char m_ch;
|
||||
};
|
||||
|
||||
MyThread::MyThread(char ch)
|
||||
{
|
||||
m_ch = ch;
|
||||
|
||||
Create();
|
||||
}
|
||||
|
||||
void *MyThread::Entry()
|
||||
wxThread::ExitCode MyDetachedThread::Entry()
|
||||
{
|
||||
{
|
||||
wxCriticalSectionLocker lock(gs_critsect);
|
||||
@@ -80,7 +101,8 @@ void *MyThread::Entry()
|
||||
gs_counter++;
|
||||
}
|
||||
|
||||
for ( size_t n = 0; n < 10; n++ )
|
||||
static const size_t nIter = 10;
|
||||
for ( size_t n = 0; n < nIter; n++ )
|
||||
{
|
||||
if ( TestDestroy() )
|
||||
break;
|
||||
@@ -91,13 +113,14 @@ void *MyThread::Entry()
|
||||
wxThread::Sleep(100);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MyThread::OnExit()
|
||||
void MyDetachedThread::OnExit()
|
||||
{
|
||||
wxCriticalSectionLocker lock(gs_critsect);
|
||||
gs_counter--;
|
||||
if ( !--gs_counter )
|
||||
gs_cond.Signal();
|
||||
}
|
||||
|
||||
#endif // TEST_THREADS
|
||||
@@ -178,33 +201,44 @@ int main(int argc, char **argv)
|
||||
printf(msg);
|
||||
|
||||
// but this one will because log functions use fixed size buffer
|
||||
wxLogMessage("A very very long message 2: '%s', the end!\n", s.c_str());
|
||||
// (note that it doesn't need '\n' at the end neither - will be added
|
||||
// by wxLog anyhow)
|
||||
wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
|
||||
#endif // TEST_LOG
|
||||
|
||||
#ifdef TEST_THREADS
|
||||
puts("Testing detached threads...");
|
||||
|
||||
static const size_t nThreads = 3;
|
||||
MyThread *threads[nThreads];
|
||||
MyDetachedThread *threads[nThreads];
|
||||
size_t n;
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n] = new MyThread('+' + n);
|
||||
threads[n] = new MyDetachedThread('A' + n);
|
||||
}
|
||||
|
||||
threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
|
||||
threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
|
||||
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n]->Run();
|
||||
}
|
||||
|
||||
// wait until all threads terminate
|
||||
for ( ;; )
|
||||
{
|
||||
wxCriticalSectionLocker lock(gs_critsect);
|
||||
if ( !gs_counter )
|
||||
break;
|
||||
}
|
||||
wxMutex mutex;
|
||||
mutex.Lock();
|
||||
gs_cond.Wait(mutex);
|
||||
mutex.Unlock();
|
||||
|
||||
puts("\nThat's all, folks!");
|
||||
puts("\n\nTesting a joinable thread used for a loooong calculation...");
|
||||
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n]->Delete();
|
||||
}
|
||||
// calc 10! in the background
|
||||
MyJoinableThread thread(10);
|
||||
thread.Run();
|
||||
|
||||
printf("\nThread terminated with exit code %lu.\n",
|
||||
(unsigned long)thread.Wait());
|
||||
#endif // TEST_THREADS
|
||||
|
||||
wxUninitialize();
|
||||
|
@@ -150,7 +150,7 @@ void *MyThread::Entry()
|
||||
wxString text;
|
||||
|
||||
text.Printf("Thread 0x%x started (priority = %d).\n",
|
||||
GetID(), GetPriority());
|
||||
GetId(), GetPriority());
|
||||
WriteText(text);
|
||||
|
||||
for ( m_count = 0; m_count < 10; m_count++ )
|
||||
@@ -159,14 +159,14 @@ void *MyThread::Entry()
|
||||
if ( TestDestroy() )
|
||||
break;
|
||||
|
||||
text.Printf("[%u] Thread 0x%x here.\n", m_count, GetID());
|
||||
text.Printf("[%u] Thread 0x%x here.\n", m_count, GetId());
|
||||
WriteText(text);
|
||||
|
||||
// wxSleep() can't be called from non-GUI thread!
|
||||
wxThread::Sleep(1000);
|
||||
}
|
||||
|
||||
text.Printf("Thread 0x%x finished.\n", GetID());
|
||||
text.Printf("Thread 0x%x finished.\n", GetId());
|
||||
WriteText(text);
|
||||
|
||||
return NULL;
|
||||
@@ -266,17 +266,18 @@ MyThread *MyFrame::CreateThread()
|
||||
|
||||
void MyFrame::OnStartThreads(wxCommandEvent& WXUNUSED(event) )
|
||||
{
|
||||
static wxString s_str;
|
||||
s_str = wxGetTextFromUser("How many threads to start: ",
|
||||
"wxThread sample",
|
||||
s_str, this);
|
||||
if ( s_str.IsEmpty() )
|
||||
return;
|
||||
static long s_num = 10;
|
||||
|
||||
s_num = wxGetNumberFromUser("How many threads to start: ", "",
|
||||
"wxThread sample", s_num, 1, 10000, this);
|
||||
if ( s_num == -1 )
|
||||
{
|
||||
s_num = 10;
|
||||
|
||||
size_t count, n;
|
||||
sscanf(s_str, "%u", &count);
|
||||
if ( count == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = (size_t)s_num, n;
|
||||
|
||||
wxArrayThread threads;
|
||||
|
||||
|
@@ -47,7 +47,7 @@
|
||||
void wxAppBase::ProcessPendingEvents()
|
||||
{
|
||||
// ensure that we're the only thread to modify the pending events list
|
||||
wxCRIT_SECT_LOCKER(locker, wxPendingEventsLocker);
|
||||
wxCRIT_SECT_LOCKER(locker, *wxPendingEventsLocker);
|
||||
|
||||
if ( !wxPendingEvents )
|
||||
return;
|
||||
|
@@ -609,13 +609,13 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event)
|
||||
|
||||
m_pendingEvents->Append(event2);
|
||||
|
||||
wxENTER_CRIT_SECT(wxPendingEventsLocker);
|
||||
wxENTER_CRIT_SECT(*wxPendingEventsLocker);
|
||||
|
||||
if ( !wxPendingEvents )
|
||||
wxPendingEvents = new wxList;
|
||||
wxPendingEvents->Append(this);
|
||||
|
||||
wxLEAVE_CRIT_SECT(wxPendingEventsLocker);
|
||||
wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
|
||||
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
@@ -623,9 +623,9 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event)
|
||||
void wxEvtHandler::ProcessPendingEvents()
|
||||
{
|
||||
#if defined(__VISAGECPP__)
|
||||
wxCRIT_SECT_LOCKER(locker, &m_eventsLocker);
|
||||
#else
|
||||
wxCRIT_SECT_LOCKER(locker, m_eventsLocker);
|
||||
#else
|
||||
wxCRIT_SECT_LOCKER(locker, *m_eventsLocker);
|
||||
#endif
|
||||
|
||||
wxNode *node = m_pendingEvents->First();
|
||||
|
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "wx/module.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// global vars
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include "wx/utils.h"
|
||||
#include "wx/wxchar.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/thread.h"
|
||||
|
||||
// other standard headers
|
||||
#include <errno.h>
|
||||
@@ -55,9 +56,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __WXMSW__
|
||||
#include <windows.h>
|
||||
// Redefines OutputDebugString if necessary
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/msw/private.h" // includes windows.h for OutputDebugString
|
||||
#else //Unix
|
||||
#include <signal.h>
|
||||
#endif //Win/Unix
|
||||
@@ -78,23 +77,36 @@
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// implementation of Log functions
|
||||
//
|
||||
// NB: unfortunately we need all these distinct functions, we can't make them
|
||||
// macros and not all compilers inline vararg functions.
|
||||
// globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// log functions can't allocate memory (LogError("out of memory...") should
|
||||
// work!), so we use a static buffer for all log messages
|
||||
#define LOG_BUFFER_SIZE (4096)
|
||||
|
||||
// static buffer for error messages (FIXME MT-unsafe)
|
||||
// static buffer for error messages
|
||||
static wxChar s_szBuf[LOG_BUFFER_SIZE];
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
// the critical section protecting the static buffer
|
||||
static wxCriticalSection gs_csLogBuf;
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// implementation of Log functions
|
||||
//
|
||||
// NB: unfortunately we need all these distinct functions, we can't make them
|
||||
// macros and not all compilers inline vararg functions.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// generic log function
|
||||
void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...)
|
||||
{
|
||||
if ( wxLog::GetActiveTarget() != NULL ) {
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -108,6 +120,8 @@ void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...)
|
||||
void wxLog##level(const wxChar *szFormat, ...) \
|
||||
{ \
|
||||
if ( wxLog::GetActiveTarget() != NULL ) { \
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \
|
||||
\
|
||||
va_list argptr; \
|
||||
va_start(argptr, szFormat); \
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \
|
||||
@@ -129,6 +143,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
|
||||
{
|
||||
wxLog *pLog = wxLog::GetActiveTarget();
|
||||
if ( pLog != NULL && pLog->GetVerbose() ) {
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -144,6 +160,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
|
||||
void wxLog##level(const wxChar *szFormat, ...) \
|
||||
{ \
|
||||
if ( wxLog::GetActiveTarget() != NULL ) { \
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \
|
||||
\
|
||||
va_list argptr; \
|
||||
va_start(argptr, szFormat); \
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \
|
||||
@@ -158,6 +176,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
|
||||
wxLog *pLog = wxLog::GetActiveTarget();
|
||||
|
||||
if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) {
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -175,6 +195,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
|
||||
// that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something
|
||||
// if both bits are set.
|
||||
if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) {
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -207,6 +229,8 @@ void wxLogSysErrorHelper(long lErrCode)
|
||||
|
||||
void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...)
|
||||
{
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -217,6 +241,8 @@ void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...)
|
||||
|
||||
void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...)
|
||||
{
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
@@ -361,15 +387,16 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t))
|
||||
{
|
||||
wxString str;
|
||||
TimeStamp(&str);
|
||||
str << szString << wxT('\n');
|
||||
str << szString;
|
||||
|
||||
fputs(str.mb_str(), m_fp);
|
||||
fputc(_T('\n'), m_fp);
|
||||
fflush(m_fp);
|
||||
|
||||
// under Windows, programs usually don't have stderr at all, so show the
|
||||
// messages also under debugger
|
||||
#ifdef __WXMSW__
|
||||
OutputDebugString(str + wxT('\r'));
|
||||
// messages also under debugger - unless it's a console program
|
||||
#if defined(__WXMSW__) && wxUSE_GUI
|
||||
OutputDebugString(str + wxT("\r\n"));
|
||||
#endif // MSW
|
||||
}
|
||||
|
||||
|
@@ -771,6 +771,7 @@ bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
|
||||
|
||||
bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if ( m_info ) {
|
||||
// we don't have icons in the fallback resources
|
||||
return FALSE;
|
||||
@@ -819,6 +820,8 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
|
||||
}
|
||||
|
||||
// no such file type or no value or incorrect icon entry
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@@ -200,7 +200,12 @@ extern int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len,
|
||||
|
||||
return iLen;
|
||||
#else // ANSI
|
||||
return wxVsnprintfA(buf, len, format, argptr);
|
||||
// vsnprintf() will not terminate the string with '\0' if there is not
|
||||
// enough place, but we want the string to always be NUL terminated
|
||||
int rc = wxVsnprintfA(buf, len - 1, format, argptr);
|
||||
buf[len] = 0;
|
||||
|
||||
return rc;
|
||||
#endif // Unicode/ANSI
|
||||
}
|
||||
|
||||
|
@@ -100,7 +100,6 @@ extern wxList WXDLLEXPORT wxPendingDelete;
|
||||
extern void wxSetKeyboardHook(bool doIt);
|
||||
extern wxCursor *g_globalCursor;
|
||||
|
||||
HINSTANCE wxhInstance = 0;
|
||||
MSG s_currentMsg;
|
||||
wxApp *wxTheApp = NULL;
|
||||
|
||||
@@ -1217,11 +1216,16 @@ void wxWakeUpIdle()
|
||||
{
|
||||
// Send the top window a dummy message so idle handler processing will
|
||||
// start up again. Doing it this way ensures that the idle handler
|
||||
// wakes up in the right thread.
|
||||
// wakes up in the right thread (see also wxWakeUpMainThread() which does
|
||||
// the same for the main app thread only)
|
||||
wxWindow *topWindow = wxTheApp->GetTopWindow();
|
||||
if ( topWindow ) {
|
||||
HWND hWnd = (HWND)topWindow->GetHWND();
|
||||
::PostMessage(hWnd, WM_NULL, 0, 0);
|
||||
if ( topWindow )
|
||||
{
|
||||
if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
|
||||
{
|
||||
// should never happen
|
||||
wxLogLastError("PostMessage(WM_NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1250,17 +1254,6 @@ wxApp::GetStdIcon(int which) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HINSTANCE wxGetInstance()
|
||||
{
|
||||
return wxhInstance;
|
||||
}
|
||||
|
||||
void wxSetInstance(HINSTANCE hInst)
|
||||
{
|
||||
wxhInstance = hInst;
|
||||
}
|
||||
|
||||
// For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
|
||||
// if in a separate file. So include it here to ensure it's linked.
|
||||
#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))
|
||||
|
@@ -1,36 +1,59 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: main.cpp
|
||||
// Name: msw/main.cpp
|
||||
// Purpose: Main/DllMain
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 04/01/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart and Markus Holzem
|
||||
// Licence: wxWindows license
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "wx/event.h"
|
||||
#include "wx/app.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
HINSTANCE wxhInstance = 0;
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// various entry points
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// May wish not to have a DllMain or WinMain, e.g. if we're programming
|
||||
// a Netscape plugin.
|
||||
#ifndef NOMAIN
|
||||
// a Netscape plugin or if we're writing a console application
|
||||
#if wxUSE_GUI && !defined(NOMAIN)
|
||||
|
||||
// NT defines APIENTRY, 3.x not
|
||||
#if !defined(APIENTRY)
|
||||
#define APIENTRY FAR PASCAL
|
||||
#define APIENTRY FAR PASCAL
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -78,25 +101,39 @@ BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
|
||||
#endif
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Only call wxEntry if the application itself is part of the DLL.
|
||||
// If only the wxWindows library is in the DLL, then the initialisation
|
||||
// will be called when the application implicitly calls WinMain.
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Only call wxEntry if the application itself is part of the DLL.
|
||||
// If only the wxWindows library is in the DLL, then the initialisation
|
||||
// will be called when the application implicitly calls WinMain.
|
||||
|
||||
#if !defined(WXMAKINGDLL)
|
||||
return wxEntry((WXHINSTANCE) hModule);
|
||||
return wxEntry((WXHINSTANCE) hModule);
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
case DLL_PROCESS_DETACH:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // _WINDLL
|
||||
|
||||
#endif
|
||||
#endif // !NOMAIN
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// global functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
HINSTANCE wxGetInstance()
|
||||
{
|
||||
return wxhInstance;
|
||||
}
|
||||
|
||||
void wxSetInstance(HINSTANCE hInst)
|
||||
{
|
||||
wxhInstance = hInst;
|
||||
}
|
||||
|
||||
|
@@ -160,13 +160,25 @@ void wxRegConfig::SetPath(const wxString& strPath)
|
||||
}
|
||||
|
||||
// recombine path parts in one variable
|
||||
wxString strRegPath;
|
||||
wxString strOldPath = m_strPath, strRegPath;
|
||||
m_strPath.Empty();
|
||||
for ( size_t n = 0; n < aParts.Count(); n++ ) {
|
||||
strRegPath << '\\' << aParts[n];
|
||||
m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n];
|
||||
}
|
||||
|
||||
if ( m_strPath == strOldPath )
|
||||
return;
|
||||
|
||||
// as we create the registry key when SetPath(key) is done, we can be left
|
||||
// with plenty of empty keys if this was only done to try to read some value
|
||||
// which, in fact, doesn't exist - to prevent this from happening we
|
||||
// automatically delete the old key if it was empty
|
||||
if ( m_keyLocal.IsEmpty() )
|
||||
{
|
||||
m_keyLocal.DeleteSelf();
|
||||
}
|
||||
|
||||
// change current key(s)
|
||||
m_keyLocal.SetName(m_keyLocalRoot, strRegPath);
|
||||
m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath);
|
||||
|
@@ -36,6 +36,19 @@
|
||||
#include "wx/module.h"
|
||||
#include "wx/thread.h"
|
||||
|
||||
// must have this symbol defined to get _beginthread/_endthread declarations
|
||||
#ifndef _MT
|
||||
#define _MT
|
||||
#endif
|
||||
|
||||
#ifdef __VISUALC__
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// the possible states of the thread ("=>" shows all possible transitions from
|
||||
// this state)
|
||||
enum wxThreadState
|
||||
@@ -48,32 +61,32 @@ enum wxThreadState
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// static variables
|
||||
// this module globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TLS index of the slot where we store the pointer to the current thread
|
||||
static DWORD s_tlsThisThread = 0xFFFFFFFF;
|
||||
static DWORD gs_tlsThisThread = 0xFFFFFFFF;
|
||||
|
||||
// id of the main thread - the one which can call GUI functions without first
|
||||
// calling wxMutexGuiEnter()
|
||||
static DWORD s_idMainThread = 0;
|
||||
static DWORD gs_idMainThread = 0;
|
||||
|
||||
// if it's FALSE, some secondary thread is holding the GUI lock
|
||||
static bool s_bGuiOwnedByMainThread = TRUE;
|
||||
static bool gs_bGuiOwnedByMainThread = TRUE;
|
||||
|
||||
// critical section which controls access to all GUI functions: any secondary
|
||||
// thread (i.e. except the main one) must enter this crit section before doing
|
||||
// any GUI calls
|
||||
static wxCriticalSection *s_critsectGui = NULL;
|
||||
static wxCriticalSection *gs_critsectGui = NULL;
|
||||
|
||||
// critical section which protects s_nWaitingForGui variable
|
||||
static wxCriticalSection *s_critsectWaitingForGui = NULL;
|
||||
// critical section which protects gs_nWaitingForGui variable
|
||||
static wxCriticalSection *gs_critsectWaitingForGui = NULL;
|
||||
|
||||
// number of threads waiting for GUI in wxMutexGuiEnter()
|
||||
static size_t s_nWaitingForGui = 0;
|
||||
static size_t gs_nWaitingForGui = 0;
|
||||
|
||||
// are we waiting for a thread termination?
|
||||
static bool s_waitingForThread = FALSE;
|
||||
static bool gs_waitingForThread = FALSE;
|
||||
|
||||
// ============================================================================
|
||||
// Windows implementation of thread classes
|
||||
@@ -169,6 +182,46 @@ wxMutexError wxMutex::Unlock()
|
||||
class wxConditionInternal
|
||||
{
|
||||
public:
|
||||
wxConditionInternal()
|
||||
{
|
||||
event = ::CreateEvent(
|
||||
NULL, // default secutiry
|
||||
FALSE, // not manual reset
|
||||
FALSE, // nonsignaled initially
|
||||
NULL // nameless event
|
||||
);
|
||||
if ( !event )
|
||||
{
|
||||
wxLogSysError(_("Can not create event object."));
|
||||
}
|
||||
waiters = 0;
|
||||
}
|
||||
|
||||
bool Wait(wxMutex& mutex, DWORD timeout)
|
||||
{
|
||||
mutex.Unlock();
|
||||
waiters++;
|
||||
|
||||
// FIXME this should be MsgWaitForMultipleObjects() as well probably
|
||||
DWORD rc = ::WaitForSingleObject(event, timeout);
|
||||
|
||||
waiters--;
|
||||
mutex.Lock();
|
||||
|
||||
return rc != WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
~wxConditionInternal()
|
||||
{
|
||||
if ( event )
|
||||
{
|
||||
if ( !::CloseHandle(event) )
|
||||
{
|
||||
wxLogLastError("CloseHandle(event)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE event;
|
||||
int waiters;
|
||||
};
|
||||
@@ -176,59 +229,46 @@ public:
|
||||
wxCondition::wxCondition()
|
||||
{
|
||||
p_internal = new wxConditionInternal;
|
||||
p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if ( !p_internal->event )
|
||||
{
|
||||
wxLogSysError(_("Can not create event object."));
|
||||
}
|
||||
|
||||
p_internal->waiters = 0;
|
||||
}
|
||||
|
||||
wxCondition::~wxCondition()
|
||||
{
|
||||
CloseHandle(p_internal->event);
|
||||
delete p_internal;
|
||||
}
|
||||
|
||||
void wxCondition::Wait(wxMutex& mutex)
|
||||
{
|
||||
mutex.Unlock();
|
||||
p_internal->waiters++;
|
||||
WaitForSingleObject(p_internal->event, INFINITE);
|
||||
p_internal->waiters--;
|
||||
mutex.Lock();
|
||||
(void)p_internal->Wait(mutex, INFINITE);
|
||||
}
|
||||
|
||||
bool wxCondition::Wait(wxMutex& mutex,
|
||||
unsigned long sec,
|
||||
unsigned long nsec)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
mutex.Unlock();
|
||||
p_internal->waiters++;
|
||||
ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000));
|
||||
p_internal->waiters--;
|
||||
mutex.Lock();
|
||||
|
||||
return (ret != WAIT_TIMEOUT);
|
||||
return p_internal->Wait(mutex, sec*1000 + nsec/1000000);
|
||||
}
|
||||
|
||||
void wxCondition::Signal()
|
||||
{
|
||||
SetEvent(p_internal->event);
|
||||
// set the event to signaled: if a thread is already waiting on it, it will
|
||||
// be woken up, otherwise the event will remain in the signaled state until
|
||||
// someone waits on it. In any case, the system will return it to a non
|
||||
// signalled state afterwards. If multiple threads are waiting, only one
|
||||
// will be woken up.
|
||||
if ( !::SetEvent(p_internal->event) )
|
||||
{
|
||||
wxLogLastError("SetEvent");
|
||||
}
|
||||
}
|
||||
|
||||
void wxCondition::Broadcast()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<p_internal->waiters;i++)
|
||||
// this works because all these threads are already waiting and so each
|
||||
// SetEvent() inside Signal() is really a PulseEvent() because the event
|
||||
// state is immediately returned to non-signaled
|
||||
for ( int i = 0; i < p_internal->waiters; i++ )
|
||||
{
|
||||
if ( SetEvent(p_internal->event) == 0 )
|
||||
{
|
||||
wxLogSysError(_("Couldn't change the state of event object."));
|
||||
}
|
||||
Signal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +278,7 @@ void wxCondition::Broadcast()
|
||||
|
||||
wxCriticalSection::wxCriticalSection()
|
||||
{
|
||||
wxASSERT_MSG( sizeof(CRITICAL_SECTION) == sizeof(m_buffer),
|
||||
wxASSERT_MSG( sizeof(CRITICAL_SECTION) <= sizeof(m_buffer),
|
||||
_T("must increase buffer size in wx/thread.h") );
|
||||
|
||||
::InitializeCriticalSection((CRITICAL_SECTION *)m_buffer);
|
||||
@@ -276,6 +316,24 @@ public:
|
||||
m_priority = WXTHREAD_DEFAULT_PRIORITY;
|
||||
}
|
||||
|
||||
~wxThreadInternal()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void Free()
|
||||
{
|
||||
if ( m_hThread )
|
||||
{
|
||||
if ( !::CloseHandle(m_hThread) )
|
||||
{
|
||||
wxLogLastError("CloseHandle(thread)");
|
||||
}
|
||||
|
||||
m_hThread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// create a new (suspended) thread (for the given thread object)
|
||||
bool Create(wxThread *thread);
|
||||
|
||||
@@ -289,7 +347,7 @@ public:
|
||||
wxThreadState GetState() const { return m_state; }
|
||||
|
||||
// thread priority
|
||||
void SetPriority(unsigned int priority) { m_priority = priority; }
|
||||
void SetPriority(unsigned int priority);
|
||||
unsigned int GetPriority() const { return m_priority; }
|
||||
|
||||
// thread handle and id
|
||||
@@ -309,41 +367,38 @@ private:
|
||||
DWORD wxThreadInternal::WinThreadStart(wxThread *thread)
|
||||
{
|
||||
// store the thread object in the TLS
|
||||
if ( !::TlsSetValue(s_tlsThisThread, thread) )
|
||||
if ( !::TlsSetValue(gs_tlsThisThread, thread) )
|
||||
{
|
||||
wxLogSysError(_("Can not start thread: error writing TLS."));
|
||||
|
||||
return (DWORD)-1;
|
||||
}
|
||||
|
||||
DWORD ret = (DWORD)thread->Entry();
|
||||
DWORD rc = (DWORD)thread->Entry();
|
||||
|
||||
// enter m_critsect before changing the thread state
|
||||
thread->m_critsect.Enter();
|
||||
bool wasCancelled = thread->p_internal->GetState() == STATE_CANCELED;
|
||||
thread->p_internal->SetState(STATE_EXITED);
|
||||
thread->m_critsect.Leave();
|
||||
|
||||
thread->OnExit();
|
||||
|
||||
delete thread;
|
||||
// if the thread was cancelled (from Delete()), then it the handle is still
|
||||
// needed there
|
||||
if ( thread->IsDetached() && !wasCancelled )
|
||||
{
|
||||
// auto delete
|
||||
delete thread;
|
||||
}
|
||||
//else: the joinable threads handle will be closed when Wait() is done
|
||||
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool wxThreadInternal::Create(wxThread *thread)
|
||||
void wxThreadInternal::SetPriority(unsigned int priority)
|
||||
{
|
||||
m_hThread = ::CreateThread
|
||||
(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE) // thread entry point
|
||||
wxThreadInternal::WinThreadStart, //
|
||||
(LPVOID)thread, // parameter
|
||||
CREATE_SUSPENDED, // flags
|
||||
&m_tid // [out] thread id
|
||||
);
|
||||
|
||||
if ( m_hThread == NULL )
|
||||
{
|
||||
wxLogSysError(_("Can't create thread"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
m_priority = priority;
|
||||
|
||||
// translate wxWindows priority to the Windows one
|
||||
int win_priority;
|
||||
@@ -363,10 +418,49 @@ bool wxThreadInternal::Create(wxThread *thread)
|
||||
win_priority = THREAD_PRIORITY_NORMAL;
|
||||
}
|
||||
|
||||
if ( ::SetThreadPriority(m_hThread, win_priority) == 0 )
|
||||
if ( !::SetThreadPriority(m_hThread, win_priority) )
|
||||
{
|
||||
wxLogSysError(_("Can't set thread priority"));
|
||||
}
|
||||
}
|
||||
|
||||
bool wxThreadInternal::Create(wxThread *thread)
|
||||
{
|
||||
// for compilers which have it, we should use C RTL function for thread
|
||||
// creation instead of Win32 API one because otherwise we will have memory
|
||||
// leaks if the thread uses C RTL (and most threads do)
|
||||
#ifdef __VISUALC__
|
||||
typedef unsigned (__stdcall *RtlThreadStart)(void *);
|
||||
|
||||
m_hThread = (HANDLE)_beginthreadex(NULL, 0,
|
||||
(RtlThreadStart)
|
||||
wxThreadInternal::WinThreadStart,
|
||||
thread, CREATE_SUSPENDED,
|
||||
(unsigned int *)&m_tid);
|
||||
#else // !VC++
|
||||
m_hThread = ::CreateThread
|
||||
(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE) // thread entry point
|
||||
wxThreadInternal::WinThreadStart, //
|
||||
(LPVOID)thread, // parameter
|
||||
CREATE_SUSPENDED, // flags
|
||||
&m_tid // [out] thread id
|
||||
);
|
||||
#endif // VC++/!VC++
|
||||
|
||||
if ( m_hThread == NULL )
|
||||
{
|
||||
wxLogSysError(_("Can't create thread"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( m_priority != WXTHREAD_DEFAULT_PRIORITY )
|
||||
{
|
||||
SetPriority(m_priority);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -406,7 +500,7 @@ bool wxThreadInternal::Resume()
|
||||
|
||||
wxThread *wxThread::This()
|
||||
{
|
||||
wxThread *thread = (wxThread *)::TlsGetValue(s_tlsThisThread);
|
||||
wxThread *thread = (wxThread *)::TlsGetValue(gs_tlsThisThread);
|
||||
|
||||
// be careful, 0 may be a valid return value as well
|
||||
if ( !thread && (::GetLastError() != NO_ERROR) )
|
||||
@@ -421,16 +515,13 @@ wxThread *wxThread::This()
|
||||
|
||||
bool wxThread::IsMain()
|
||||
{
|
||||
return ::GetCurrentThreadId() == s_idMainThread;
|
||||
return ::GetCurrentThreadId() == gs_idMainThread;
|
||||
}
|
||||
|
||||
#ifdef Yield
|
||||
#undef Yield
|
||||
#endif
|
||||
|
||||
void wxThread::Yield()
|
||||
{
|
||||
// 0 argument to Sleep() is special
|
||||
// 0 argument to Sleep() is special and means to just give away the rest of
|
||||
// our timeslice
|
||||
::Sleep(0);
|
||||
}
|
||||
|
||||
@@ -439,11 +530,28 @@ void wxThread::Sleep(unsigned long milliseconds)
|
||||
::Sleep(milliseconds);
|
||||
}
|
||||
|
||||
// ctor and dtor
|
||||
// -------------
|
||||
|
||||
wxThread::wxThread(wxThreadKind kind)
|
||||
{
|
||||
p_internal = new wxThreadInternal();
|
||||
|
||||
m_isDetached = kind == wxTHREAD_DETACHED;
|
||||
}
|
||||
|
||||
wxThread::~wxThread()
|
||||
{
|
||||
delete p_internal;
|
||||
}
|
||||
|
||||
// create/start thread
|
||||
// -------------------
|
||||
|
||||
wxThreadError wxThread::Create()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
if ( !p_internal->Create(this) )
|
||||
return wxTHREAD_NO_RESOURCE;
|
||||
|
||||
@@ -460,6 +568,7 @@ wxThreadError wxThread::Run()
|
||||
return wxTHREAD_RUNNING;
|
||||
}
|
||||
|
||||
// the thread has just been created and is still suspended - let it run
|
||||
return Resume();
|
||||
}
|
||||
|
||||
@@ -483,7 +592,23 @@ wxThreadError wxThread::Resume()
|
||||
// stopping thread
|
||||
// ---------------
|
||||
|
||||
wxThread::ExitCode wxThread::Delete()
|
||||
wxThread::ExitCode wxThread::Wait()
|
||||
{
|
||||
// although under Windows we can wait for any thread, it's an error to
|
||||
// wait for a detached one in wxWin API
|
||||
wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
|
||||
_T("can't wait for detached thread") );
|
||||
|
||||
ExitCode rc = (ExitCode)-1;
|
||||
|
||||
(void)Delete(&rc);
|
||||
|
||||
p_internal->Free();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
wxThreadError wxThread::Delete(ExitCode *pRc)
|
||||
{
|
||||
ExitCode rc = 0;
|
||||
|
||||
@@ -491,24 +616,28 @@ wxThread::ExitCode wxThread::Delete()
|
||||
if ( IsPaused() )
|
||||
Resume();
|
||||
|
||||
HANDLE hThread = p_internal->GetHandle();
|
||||
|
||||
if ( IsRunning() )
|
||||
{
|
||||
if ( IsMain() )
|
||||
{
|
||||
// set flag for wxIsWaitingForThread()
|
||||
s_waitingForThread = TRUE;
|
||||
gs_waitingForThread = TRUE;
|
||||
|
||||
#if wxUSE_GUI
|
||||
wxBeginBusyCursor();
|
||||
#endif // wxUSE_GUI
|
||||
}
|
||||
|
||||
HANDLE hThread;
|
||||
// ask the thread to terminate
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
p_internal->Cancel();
|
||||
hThread = p_internal->GetHandle();
|
||||
}
|
||||
|
||||
#if wxUSE_GUI
|
||||
// we can't just wait for the thread to terminate because it might be
|
||||
// calling some GUI functions and so it will never terminate before we
|
||||
// process the Windows messages that result from these functions
|
||||
@@ -530,7 +659,7 @@ wxThread::ExitCode wxThread::Delete()
|
||||
// error
|
||||
wxLogSysError(_("Can not wait for thread termination"));
|
||||
Kill();
|
||||
return (ExitCode)-1;
|
||||
return wxTHREAD_KILLED;
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
// thread we're waiting for terminated
|
||||
@@ -543,14 +672,14 @@ wxThread::ExitCode wxThread::Delete()
|
||||
// WM_QUIT received: kill the thread
|
||||
Kill();
|
||||
|
||||
return (ExitCode)-1;
|
||||
return wxTHREAD_KILLED;
|
||||
}
|
||||
|
||||
if ( IsMain() )
|
||||
{
|
||||
// give the thread we're waiting for chance to exit
|
||||
// from the GUI call it might have been in
|
||||
if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
|
||||
if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
|
||||
{
|
||||
wxMutexGuiLeave();
|
||||
}
|
||||
@@ -562,28 +691,50 @@ wxThread::ExitCode wxThread::Delete()
|
||||
wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
|
||||
}
|
||||
} while ( result != WAIT_OBJECT_0 );
|
||||
#else // !wxUSE_GUI
|
||||
// simply wait for the thread to terminate
|
||||
//
|
||||
// OTOH, even console apps create windows (in wxExecute, for WinSock
|
||||
// &c), so may be use MsgWaitForMultipleObject() too here?
|
||||
if ( WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0 )
|
||||
{
|
||||
wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject"));
|
||||
}
|
||||
#endif // wxUSE_GUI/!wxUSE_GUI
|
||||
|
||||
if ( IsMain() )
|
||||
{
|
||||
s_waitingForThread = FALSE;
|
||||
gs_waitingForThread = FALSE;
|
||||
|
||||
#if wxUSE_GUI
|
||||
wxEndBusyCursor();
|
||||
#endif // wxUSE_GUI
|
||||
}
|
||||
|
||||
if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
|
||||
{
|
||||
wxLogLastError("GetExitCodeThread");
|
||||
|
||||
rc = (ExitCode)-1;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE,
|
||||
wxT("thread must be already terminated.") );
|
||||
|
||||
::CloseHandle(hThread);
|
||||
}
|
||||
|
||||
return rc;
|
||||
if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
|
||||
{
|
||||
wxLogLastError("GetExitCodeThread");
|
||||
|
||||
rc = (ExitCode)-1;
|
||||
}
|
||||
|
||||
if ( IsDetached() )
|
||||
{
|
||||
// if the thread exits normally, this is done in WinThreadStart, but in
|
||||
// this case it would have been too early because
|
||||
// MsgWaitForMultipleObject() would fail if the therad handle was
|
||||
// closed while we were waiting on it, so we must do it here
|
||||
delete this;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( (DWORD)rc != STILL_ACTIVE,
|
||||
wxT("thread must be already terminated.") );
|
||||
|
||||
if ( pRc )
|
||||
*pRc = rc;
|
||||
|
||||
return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
|
||||
}
|
||||
|
||||
wxThreadError wxThread::Kill()
|
||||
@@ -598,20 +749,37 @@ wxThreadError wxThread::Kill()
|
||||
return wxTHREAD_MISC_ERROR;
|
||||
}
|
||||
|
||||
delete this;
|
||||
p_internal->Free();
|
||||
|
||||
if ( IsDetached() )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return wxTHREAD_NO_ERROR;
|
||||
}
|
||||
|
||||
void wxThread::Exit(void *status)
|
||||
void wxThread::Exit(ExitCode status)
|
||||
{
|
||||
delete this;
|
||||
p_internal->Free();
|
||||
|
||||
if ( IsDetached() )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
#ifdef __VISUALC__
|
||||
_endthreadex((unsigned)status);
|
||||
#else // !VC++
|
||||
::ExitThread((DWORD)status);
|
||||
#endif // VC++/!VC++
|
||||
|
||||
wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
|
||||
}
|
||||
|
||||
// priority setting
|
||||
// ----------------
|
||||
|
||||
void wxThread::SetPriority(unsigned int prio)
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
@@ -621,28 +789,28 @@ void wxThread::SetPriority(unsigned int prio)
|
||||
|
||||
unsigned int wxThread::GetPriority() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetPriority();
|
||||
}
|
||||
|
||||
unsigned long wxThread::GetID() const
|
||||
unsigned long wxThread::GetId() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return (unsigned long)p_internal->GetId();
|
||||
}
|
||||
|
||||
bool wxThread::IsRunning() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetState() == STATE_RUNNING;
|
||||
}
|
||||
|
||||
bool wxThread::IsAlive() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return (p_internal->GetState() == STATE_RUNNING) ||
|
||||
(p_internal->GetState() == STATE_PAUSED);
|
||||
@@ -650,28 +818,18 @@ bool wxThread::IsAlive() const
|
||||
|
||||
bool wxThread::IsPaused() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return (p_internal->GetState() == STATE_PAUSED);
|
||||
return p_internal->GetState() == STATE_PAUSED;
|
||||
}
|
||||
|
||||
bool wxThread::TestDestroy()
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetState() == STATE_CANCELED;
|
||||
}
|
||||
|
||||
wxThread::wxThread()
|
||||
{
|
||||
p_internal = new wxThreadInternal();
|
||||
}
|
||||
|
||||
wxThread::~wxThread()
|
||||
{
|
||||
delete p_internal;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Automatic initialization for thread module
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -691,8 +849,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
|
||||
bool wxThreadModule::OnInit()
|
||||
{
|
||||
// allocate TLS index for storing the pointer to the current thread
|
||||
s_tlsThisThread = ::TlsAlloc();
|
||||
if ( s_tlsThisThread == 0xFFFFFFFF )
|
||||
gs_tlsThisThread = ::TlsAlloc();
|
||||
if ( gs_tlsThisThread == 0xFFFFFFFF )
|
||||
{
|
||||
// in normal circumstances it will only happen if all other
|
||||
// TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other
|
||||
@@ -706,10 +864,10 @@ bool wxThreadModule::OnInit()
|
||||
|
||||
// main thread doesn't have associated wxThread object, so store 0 in the
|
||||
// TLS instead
|
||||
if ( !::TlsSetValue(s_tlsThisThread, (LPVOID)0) )
|
||||
if ( !::TlsSetValue(gs_tlsThisThread, (LPVOID)0) )
|
||||
{
|
||||
::TlsFree(s_tlsThisThread);
|
||||
s_tlsThisThread = 0xFFFFFFFF;
|
||||
::TlsFree(gs_tlsThisThread);
|
||||
gs_tlsThisThread = 0xFFFFFFFF;
|
||||
|
||||
wxLogSysError(_("Thread module initialization failed: "
|
||||
"can not store value in thread local storage"));
|
||||
@@ -717,36 +875,37 @@ bool wxThreadModule::OnInit()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s_critsectWaitingForGui = new wxCriticalSection();
|
||||
gs_critsectWaitingForGui = new wxCriticalSection();
|
||||
|
||||
s_critsectGui = new wxCriticalSection();
|
||||
s_critsectGui->Enter();
|
||||
gs_critsectGui = new wxCriticalSection();
|
||||
gs_critsectGui->Enter();
|
||||
|
||||
// no error return for GetCurrentThreadId()
|
||||
s_idMainThread = ::GetCurrentThreadId();
|
||||
gs_idMainThread = ::GetCurrentThreadId();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxThreadModule::OnExit()
|
||||
{
|
||||
if ( !::TlsFree(s_tlsThisThread) )
|
||||
if ( !::TlsFree(gs_tlsThisThread) )
|
||||
{
|
||||
wxLogLastError("TlsFree failed.");
|
||||
}
|
||||
|
||||
if ( s_critsectGui )
|
||||
if ( gs_critsectGui )
|
||||
{
|
||||
s_critsectGui->Leave();
|
||||
delete s_critsectGui;
|
||||
s_critsectGui = NULL;
|
||||
gs_critsectGui->Leave();
|
||||
delete gs_critsectGui;
|
||||
gs_critsectGui = NULL;
|
||||
}
|
||||
|
||||
wxDELETE(s_critsectWaitingForGui);
|
||||
delete gs_critsectWaitingForGui;
|
||||
gs_critsectWaitingForGui = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// under Windows, these functions are implemented usign a critical section and
|
||||
// under Windows, these functions are implemented using a critical section and
|
||||
// not a mutex, so the names are a bit confusing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -760,38 +919,38 @@ void WXDLLEXPORT wxMutexGuiEnter()
|
||||
|
||||
// set the flag telling to the main thread that we want to do some GUI
|
||||
{
|
||||
wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
|
||||
wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
|
||||
|
||||
s_nWaitingForGui++;
|
||||
gs_nWaitingForGui++;
|
||||
}
|
||||
|
||||
wxWakeUpMainThread();
|
||||
|
||||
// now we may block here because the main thread will soon let us in
|
||||
// (during the next iteration of OnIdle())
|
||||
s_critsectGui->Enter();
|
||||
gs_critsectGui->Enter();
|
||||
}
|
||||
|
||||
void WXDLLEXPORT wxMutexGuiLeave()
|
||||
{
|
||||
wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
|
||||
wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
|
||||
|
||||
if ( wxThread::IsMain() )
|
||||
{
|
||||
s_bGuiOwnedByMainThread = FALSE;
|
||||
gs_bGuiOwnedByMainThread = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrement the number of waiters now
|
||||
wxASSERT_MSG( s_nWaitingForGui > 0,
|
||||
wxASSERT_MSG( gs_nWaitingForGui > 0,
|
||||
wxT("calling wxMutexGuiLeave() without entering it first?") );
|
||||
|
||||
s_nWaitingForGui--;
|
||||
gs_nWaitingForGui--;
|
||||
|
||||
wxWakeUpMainThread();
|
||||
}
|
||||
|
||||
s_critsectGui->Leave();
|
||||
gs_critsectGui->Leave();
|
||||
}
|
||||
|
||||
void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
|
||||
@@ -799,17 +958,17 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
|
||||
wxASSERT_MSG( wxThread::IsMain(),
|
||||
wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
|
||||
|
||||
wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
|
||||
wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
|
||||
|
||||
if ( s_nWaitingForGui == 0 )
|
||||
if ( gs_nWaitingForGui == 0 )
|
||||
{
|
||||
// no threads are waiting for GUI - so we may acquire the lock without
|
||||
// any danger (but only if we don't already have it)
|
||||
if ( !wxGuiOwnedByMainThread() )
|
||||
{
|
||||
s_critsectGui->Enter();
|
||||
gs_critsectGui->Enter();
|
||||
|
||||
s_bGuiOwnedByMainThread = TRUE;
|
||||
gs_bGuiOwnedByMainThread = TRUE;
|
||||
}
|
||||
//else: already have it, nothing to do
|
||||
}
|
||||
@@ -826,14 +985,14 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
|
||||
|
||||
bool WXDLLEXPORT wxGuiOwnedByMainThread()
|
||||
{
|
||||
return s_bGuiOwnedByMainThread;
|
||||
return gs_bGuiOwnedByMainThread;
|
||||
}
|
||||
|
||||
// wake up the main thread if it's in ::GetMessage()
|
||||
void WXDLLEXPORT wxWakeUpMainThread()
|
||||
{
|
||||
// sending any message would do - hopefully WM_NULL is harmless enough
|
||||
if ( !::PostThreadMessage(s_idMainThread, WM_NULL, 0, 0) )
|
||||
if ( !::PostThreadMessage(gs_idMainThread, WM_NULL, 0, 0) )
|
||||
{
|
||||
// should never happen
|
||||
wxLogLastError("PostThreadMessage(WM_NULL)");
|
||||
@@ -842,7 +1001,7 @@ void WXDLLEXPORT wxWakeUpMainThread()
|
||||
|
||||
bool WXDLLEXPORT wxIsWaitingForThread()
|
||||
{
|
||||
return s_waitingForThread;
|
||||
return gs_waitingForThread;
|
||||
}
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
1146
src/msw/utils.cpp
1146
src/msw/utils.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: utilsexec.cpp
|
||||
// Name: msw/utilsexec.cpp
|
||||
// Purpose: Various utilities
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
@@ -9,48 +9,51 @@
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/setup.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/intl.h"
|
||||
#endif
|
||||
|
||||
#include "wx/log.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "wx/process.h"
|
||||
#include "wx/process.h"
|
||||
#endif
|
||||
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
|
||||
#include <direct.h>
|
||||
#include <direct.h>
|
||||
#ifndef __MWERKS__
|
||||
#include <dos.h>
|
||||
#include <dos.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUWIN32__
|
||||
#ifndef __TWIN32__
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if defined(__GNUWIN32__) && !defined(__TWIN32__)
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__) && !defined(__WXWINE__)
|
||||
@@ -71,9 +74,26 @@
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// this message is sent when the process we're waiting for terminates
|
||||
#define wxWM_PROC_TERMINATED (WM_USER + 10000)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// this module globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// we need to create a hidden window to receive the process termination
|
||||
// notifications and for this we need a (Win) class name for it which we will
|
||||
// register the first time it's needed
|
||||
static const wxChar *gs_classForHiddenWindow = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// structure describing the process we're being waiting for
|
||||
struct wxExecuteData
|
||||
{
|
||||
@@ -96,6 +116,9 @@ public:
|
||||
bool state; // set to FALSE when the process finishes
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
#ifdef __WIN32__
|
||||
static DWORD wxExecuteThread(wxExecuteData *data)
|
||||
@@ -150,8 +173,6 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
|
||||
}
|
||||
#endif
|
||||
|
||||
extern wxChar wxPanelClassName[];
|
||||
|
||||
long wxExecute(const wxString& command, bool sync, wxProcess *handler)
|
||||
{
|
||||
wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
|
||||
@@ -242,17 +263,31 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler)
|
||||
if ( !::CloseHandle(pi.hThread) )
|
||||
wxLogLastError("CloseHandle(hThread)");
|
||||
|
||||
if ( !gs_classForHiddenWindow )
|
||||
{
|
||||
gs_classForHiddenWindow = _T("wxHiddenWindow");
|
||||
|
||||
WNDCLASS wndclass;
|
||||
wxZeroMemory(wndclass);
|
||||
wndclass.lpfnWndProc = (WNDPROC)wxExecuteWindowCbk;
|
||||
wndclass.hInstance = wxGetInstance();
|
||||
wndclass.lpszClassName = gs_classForHiddenWindow;
|
||||
|
||||
if ( !::RegisterClass(&wndclass) )
|
||||
{
|
||||
wxLogLastError("RegisterClass(hidden window)");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// create a hidden window to receive notification about process
|
||||
// termination
|
||||
HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
|
||||
HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL,
|
||||
0, 0, 0, 0, 0, NULL,
|
||||
(HMENU)NULL, wxGetInstance(), 0);
|
||||
wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
|
||||
|
||||
FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
|
||||
wxGetInstance());
|
||||
|
||||
::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
|
||||
|
||||
// Alloc data
|
||||
wxExecuteData *data = new wxExecuteData;
|
||||
data->hProcess = pi.hProcess;
|
||||
@@ -338,33 +373,3 @@ long wxExecute(char **argv, bool sync, wxProcess *handler)
|
||||
return wxExecute(command, sync, handler);
|
||||
}
|
||||
|
||||
bool wxGetFullHostName(wxChar *buf, int maxSize)
|
||||
{
|
||||
#if defined(__WIN32__) && !defined(__TWIN32__)
|
||||
DWORD nSize = maxSize ;
|
||||
if ( !::GetComputerName(buf, &nSize) )
|
||||
{
|
||||
wxLogLastError("GetComputerName");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
char *sysname;
|
||||
const char *default_host = "noname";
|
||||
static const char WX_SECTION[] = "wxWindows";
|
||||
static const char eHOSTNAME[] = "HostName";
|
||||
|
||||
if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
|
||||
GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
|
||||
} else
|
||||
strncpy(buf, sysname, maxSize - 1);
|
||||
buf[maxSize] = '\0';
|
||||
if ( *buf == '\0' )
|
||||
{
|
||||
wxLogLastError("GetComputerName");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -685,7 +685,14 @@ wxThreadError wxThread::Resume()
|
||||
// exiting thread
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
wxThread::ExitCode wxThread::Delete()
|
||||
wxThread::ExitCode Wait()
|
||||
{
|
||||
wxFAIL_MSG("TODO");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxThreadError wxThread::Delete(ExitCode *rc)
|
||||
{
|
||||
if (IsPaused())
|
||||
Resume();
|
||||
@@ -745,7 +752,7 @@ wxThreadError wxThread::Kill()
|
||||
}
|
||||
}
|
||||
|
||||
void wxThread::Exit(void *status)
|
||||
void wxThread::Exit(ExitCode status)
|
||||
{
|
||||
// first call user-level clean up code
|
||||
OnExit();
|
||||
|
Reference in New Issue
Block a user