aboutsummaryrefslogtreecommitdiff
path: root/src/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp479
1 files changed, 101 insertions, 378 deletions
diff --git a/src/util.cpp b/src/util.cpp
index d8804c7291..08e3625b3d 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,9 +1,10 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "util.h"
+#include "sync.h"
#include "strlcpy.h"
#include "version.h"
#include "ui_interface.h"
@@ -23,11 +24,11 @@ namespace boost {
#include <boost/program_options/parsers.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
-#include <boost/interprocess/sync/interprocess_mutex.hpp>
-#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
#include <openssl/crypto.h>
#include <openssl/rand.h>
+#include <stdarg.h>
#ifdef WIN32
#ifdef _MSC_VER
@@ -43,17 +44,16 @@ namespace boost {
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
-#define _WIN32_IE 0x0400
+#define _WIN32_IE 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
+#include <io.h> /* for _commit */
#include "shlobj.h"
-#include "shlwapi.h"
#endif
using namespace std;
-using namespace boost;
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
@@ -70,15 +70,17 @@ bool fTestNet = false;
bool fNoListen = false;
bool fLogTimestamps = false;
CMedianFilter<int64> vTimeOffsets(200,0);
+bool fReopenDebugLog = false;
// Init openssl library multithreading support
-static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
+static CCriticalSection** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
{
- if (mode & CRYPTO_LOCK)
- ppmutexOpenSSL[i]->lock();
- else
- ppmutexOpenSSL[i]->unlock();
+ if (mode & CRYPTO_LOCK) {
+ ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
+ } else {
+ LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
+ }
}
// Init
@@ -88,9 +90,9 @@ public:
CInit()
{
// Init openssl library multithreading support
- ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
+ ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
for (int i = 0; i < CRYPTO_num_locks(); i++)
- ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
+ ppmutexOpenSSL[i] = new CCriticalSection();
CRYPTO_set_locking_callback(locking_callback);
#ifdef WIN32
@@ -149,7 +151,7 @@ void RandAddSeedPerfmon()
{
RAND_add(pdata, nSize, nSize/100.0);
memset(pdata, 0, nSize);
- printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
+ printf("RandAddSeed() %d bytes\n", nSize);
}
#endif
}
@@ -188,8 +190,6 @@ uint256 GetRandHash()
-
-
inline int OutputDebugStringF(const char* pszFormat, ...)
{
int ret = 0;
@@ -215,6 +215,16 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
if (fileout)
{
static bool fStartedNewLine = true;
+ static boost::mutex mutexDebugLog;
+ boost::mutex::scoped_lock scoped_lock(mutexDebugLog);
+
+ // reopen the log file, if requested
+ if (fReopenDebugLog) {
+ fReopenDebugLog = false;
+ boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
+ if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
+ setbuf(fileout, NULL); // unbuffered
+ }
// Debug print useful for profiling
if (fLogTimestamps && fStartedNewLine)
@@ -236,68 +246,30 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
{
static CCriticalSection cs_OutputDebugStringF;
- // accumulate a line at a time
+ // accumulate and output a line at a time
{
LOCK(cs_OutputDebugStringF);
- static char pszBuffer[50000];
- static char* pend;
- if (pend == NULL)
- pend = pszBuffer;
+ static std::string buffer;
+
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
- int limit = END(pszBuffer) - pend - 2;
- int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
+ buffer += vstrprintf(pszFormat, arg_ptr);
va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- pend = END(pszBuffer) - 2;
- *pend++ = '\n';
- }
- else
- pend += ret;
- *pend = '\0';
- char* p1 = pszBuffer;
- char* p2;
- while ((p2 = strchr(p1, '\n')))
+
+ int line_start = 0, line_end;
+ while((line_end = buffer.find('\n', line_start)) != -1)
{
- p2++;
- char c = *p2;
- *p2 = '\0';
- OutputDebugStringA(p1);
- *p2 = c;
- p1 = p2;
+ OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str());
+ line_start = line_end + 1;
}
- if (p1 != pszBuffer)
- memmove(pszBuffer, p1, pend - p1 + 1);
- pend -= (p1 - pszBuffer);
+ buffer.erase(0, line_start);
}
}
#endif
return ret;
}
-
-// Safer snprintf
-// - prints up to limit-1 characters
-// - output string is always null terminated even if limit reached
-// - return value is the number of characters actually printed
-int my_snprintf(char* buffer, size_t limit, const char* format, ...)
-{
- if (limit == 0)
- return 0;
- va_list arg_ptr;
- va_start(arg_ptr, format);
- int ret = _vsnprintf(buffer, limit, format, arg_ptr);
- va_end(arg_ptr);
- if (ret < 0 || ret >= (int)limit)
- {
- ret = limit - 1;
- buffer[limit-1] = 0;
- }
- return ret;
-}
-
-string real_strprintf(const std::string &format, int dummy, ...)
+string vstrprintf(const std::string &format, va_list ap)
{
char buffer[50000];
char* p = buffer;
@@ -306,7 +278,7 @@ string real_strprintf(const std::string &format, int dummy, ...)
loop
{
va_list arg_ptr;
- va_start(arg_ptr, dummy);
+ va_copy(arg_ptr, ap);
ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
va_end(arg_ptr);
if (ret >= 0 && ret < limit)
@@ -324,19 +296,22 @@ string real_strprintf(const std::string &format, int dummy, ...)
return str;
}
+string real_strprintf(const std::string &format, int dummy, ...)
+{
+ va_list arg_ptr;
+ va_start(arg_ptr, dummy);
+ string str = vstrprintf(format, arg_ptr);
+ va_end(arg_ptr);
+ return str;
+}
+
bool error(const char *format, ...)
{
- char buffer[50000];
- int limit = sizeof(buffer);
va_list arg_ptr;
va_start(arg_ptr, format);
- int ret = _vsnprintf(buffer, limit, format, arg_ptr);
+ std::string str = vstrprintf(format, arg_ptr);
va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- buffer[limit-1] = 0;
- }
- printf("ERROR: %s\n", buffer);
+ printf("ERROR: %s\n", str.c_str());
return false;
}
@@ -500,7 +475,7 @@ static void InterpretNegativeSetting(string name, map<string, string>& mapSettin
}
}
-void ParseParameters(int argc, const char*const argv[])
+void ParseParameters(int argc, const char* const argv[])
{
mapArgs.clear();
mapMultiArgs.clear();
@@ -764,81 +739,55 @@ bool WildcardMatch(const string& str, const string& mask)
-void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
+static std::string FormatException(std::exception* pex, const char* pszThread)
{
#ifdef WIN32
- char pszModule[MAX_PATH];
- pszModule[0] = '\0';
+ char pszModule[MAX_PATH] = "";
GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
#else
const char* pszModule = "bitcoin";
#endif
if (pex)
- snprintf(pszMessage, 1000,
+ return strprintf(
"EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
else
- snprintf(pszMessage, 1000,
+ return strprintf(
"UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
}
void LogException(std::exception* pex, const char* pszThread)
{
- char pszMessage[10000];
- FormatException(pszMessage, pex, pszThread);
- printf("\n%s", pszMessage);
+ std::string message = FormatException(pex, pszThread);
+ printf("\n%s", message.c_str());
}
void PrintException(std::exception* pex, const char* pszThread)
{
- char pszMessage[10000];
- FormatException(pszMessage, pex, pszThread);
- printf("\n\n************************\n%s\n", pszMessage);
- fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
- strMiscWarning = pszMessage;
+ std::string message = FormatException(pex, pszThread);
+ printf("\n\n************************\n%s\n", message.c_str());
+ fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
+ strMiscWarning = message;
throw;
}
void PrintExceptionContinue(std::exception* pex, const char* pszThread)
{
- char pszMessage[10000];
- FormatException(pszMessage, pex, pszThread);
- printf("\n\n************************\n%s\n", pszMessage);
- fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
- strMiscWarning = pszMessage;
-}
-
-#ifdef WIN32
-boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate)
-{
- namespace fs = boost::filesystem;
-
- char pszPath[MAX_PATH] = "";
- if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
- {
- return fs::path(pszPath);
- }
- else if (nFolder == CSIDL_STARTUP)
- {
- return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup";
- }
- else if (nFolder == CSIDL_APPDATA)
- {
- return fs::path(getenv("APPDATA"));
- }
- return fs::path("");
+ std::string message = FormatException(pex, pszThread);
+ printf("\n\n************************\n%s\n", message.c_str());
+ fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
+ strMiscWarning = message;
}
-#endif
boost::filesystem::path GetDefaultDataDir()
{
namespace fs = boost::filesystem;
-
- // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
+ // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
+ // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
#ifdef WIN32
// Windows
- return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "Bitcoin";
+ return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
#else
fs::path pathRet;
char* pszHome = getenv("HOME");
@@ -849,7 +798,7 @@ boost::filesystem::path GetDefaultDataDir()
#ifdef MAC_OSX
// Mac
pathRet /= "Library/Application Support";
- filesystem::create_directory(pathRet);
+ fs::create_directory(pathRet);
return pathRet / "Bitcoin";
#else
// Unix
@@ -895,9 +844,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
boost::filesystem::path GetConfigFile()
{
- namespace fs = boost::filesystem;
-
- fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
+ boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
return pathConfigFile;
}
@@ -905,24 +852,21 @@ boost::filesystem::path GetConfigFile()
void ReadConfigFile(map<string, string>& mapSettingsRet,
map<string, vector<string> >& mapMultiSettingsRet)
{
- namespace fs = boost::filesystem;
- namespace pod = boost::program_options::detail;
-
- fs::ifstream streamConfig(GetConfigFile());
+ boost::filesystem::ifstream streamConfig(GetConfigFile());
if (!streamConfig.good())
return; // No bitcoin.conf file is OK
set<string> setOptions;
setOptions.insert("*");
- for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
+ for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
string strKey = string("-") + it->string_key;
if (mapSettingsRet.count(strKey) == 0)
{
mapSettingsRet[strKey] = it->value[0];
- // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
+ // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
InterpretNegativeSetting(strKey, mapSettingsRet);
}
mapMultiSettingsRet[strKey].push_back(it->value[0]);
@@ -931,9 +875,7 @@ void ReadConfigFile(map<string, string>& mapSettingsRet,
boost::filesystem::path GetPidFile()
{
- namespace fs = boost::filesystem;
-
- fs::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
+ boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
return pathPidFile;
}
@@ -948,6 +890,27 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
}
}
+bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
+{
+#ifdef WIN32
+ return MoveFileExA(src.string().c_str(), dest.string().c_str(),
+ MOVEFILE_REPLACE_EXISTING);
+#else
+ int rc = std::rename(src.string().c_str(), dest.string().c_str());
+ return (rc == 0);
+#endif /* WIN32 */
+}
+
+void FileCommit(FILE *fileout)
+{
+ fflush(fileout); // harmless if redundantly called
+#ifdef WIN32
+ _commit(_fileno(fileout));
+#else
+ fsync(fileno(fileout));
+#endif
+}
+
int GetFilesize(FILE* file)
{
int nSavePos = ftell(file);
@@ -1055,7 +1018,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION);
+ uiInterface.ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION);
}
}
}
@@ -1101,258 +1064,18 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const
}
#ifdef WIN32
-boost::filesystem::path static StartupShortcutPath()
-{
- return MyGetSpecialFolderPath(CSIDL_STARTUP, true) / "Bitcoin.lnk";
-}
-
-bool GetStartOnSystemStartup()
-{
- return filesystem::exists(StartupShortcutPath());
-}
-
-bool SetStartOnSystemStartup(bool fAutoStart)
-{
- // If the shortcut exists already, remove it for updating
- boost::filesystem::remove(StartupShortcutPath());
-
- if (fAutoStart)
- {
- CoInitialize(NULL);
-
- // Get a pointer to the IShellLink interface.
- IShellLink* psl = NULL;
- HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
- CLSCTX_INPROC_SERVER, IID_IShellLink,
- reinterpret_cast<void**>(&psl));
-
- if (SUCCEEDED(hres))
- {
- // Get the current executable path
- TCHAR pszExePath[MAX_PATH];
- GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
-
- TCHAR pszArgs[5] = TEXT("-min");
-
- // Set the path to the shortcut target
- psl->SetPath(pszExePath);
- PathRemoveFileSpec(pszExePath);
- psl->SetWorkingDirectory(pszExePath);
- psl->SetShowCmd(SW_SHOWMINNOACTIVE);
- psl->SetArguments(pszArgs);
-
- // Query IShellLink for the IPersistFile interface for
- // saving the shortcut in persistent storage.
- IPersistFile* ppf = NULL;
- hres = psl->QueryInterface(IID_IPersistFile,
- reinterpret_cast<void**>(&ppf));
- if (SUCCEEDED(hres))
- {
- WCHAR pwsz[MAX_PATH];
- // Ensure that the string is ANSI.
- MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
- // Save the link by calling IPersistFile::Save.
- hres = ppf->Save(pwsz, TRUE);
- ppf->Release();
- psl->Release();
- CoUninitialize();
- return true;
- }
- psl->Release();
- }
- CoUninitialize();
- return false;
- }
- return true;
-}
-
-#elif defined(LINUX)
-
-// Follow the Desktop Application Autostart Spec:
-// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
-
-boost::filesystem::path static GetAutostartDir()
+boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
{
namespace fs = boost::filesystem;
- char* pszConfigHome = getenv("XDG_CONFIG_HOME");
- if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
- char* pszHome = getenv("HOME");
- if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
- return fs::path();
-}
-
-boost::filesystem::path static GetAutostartFilePath()
-{
- return GetAutostartDir() / "bitcoin.desktop";
-}
+ char pszPath[MAX_PATH] = "";
-bool GetStartOnSystemStartup()
-{
- boost::filesystem::ifstream optionFile(GetAutostartFilePath());
- if (!optionFile.good())
- return false;
- // Scan through file for "Hidden=true":
- string line;
- while (!optionFile.eof())
+ if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
{
- getline(optionFile, line);
- if (line.find("Hidden") != string::npos &&
- line.find("true") != string::npos)
- return false;
+ return fs::path(pszPath);
}
- optionFile.close();
-
- return true;
-}
-bool SetStartOnSystemStartup(bool fAutoStart)
-{
- if (!fAutoStart)
- boost::filesystem::remove(GetAutostartFilePath());
- else
- {
- char pszExePath[MAX_PATH+1];
- memset(pszExePath, 0, sizeof(pszExePath));
- if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
- return false;
-
- boost::filesystem::create_directories(GetAutostartDir());
-
- boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
- if (!optionFile.good())
- return false;
- // Write a bitcoin.desktop file to the autostart directory:
- optionFile << "[Desktop Entry]\n";
- optionFile << "Type=Application\n";
- optionFile << "Name=Bitcoin\n";
- optionFile << "Exec=" << pszExePath << " -min\n";
- optionFile << "Terminal=false\n";
- optionFile << "Hidden=false\n";
- optionFile.close();
- }
- return true;
+ printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
+ return fs::path("");
}
-#else
-
-// TODO: OSX startup stuff; see:
-// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
-
-bool GetStartOnSystemStartup() { return false; }
-bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
-
#endif
-
-
-
-#ifdef DEBUG_LOCKORDER
-//
-// Early deadlock detection.
-// Problem being solved:
-// Thread 1 locks A, then B, then C
-// Thread 2 locks D, then C, then A
-// --> may result in deadlock between the two threads, depending on when they run.
-// Solution implemented here:
-// Keep track of pairs of locks: (A before B), (A before C), etc.
-// Complain if any thread trys to lock in a different order.
-//
-
-struct CLockLocation
-{
- CLockLocation(const char* pszName, const char* pszFile, int nLine)
- {
- mutexName = pszName;
- sourceFile = pszFile;
- sourceLine = nLine;
- }
-
- std::string ToString() const
- {
- return mutexName+" "+sourceFile+":"+itostr(sourceLine);
- }
-
-private:
- std::string mutexName;
- std::string sourceFile;
- int sourceLine;
-};
-
-typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
-
-static boost::interprocess::interprocess_mutex dd_mutex;
-static std::map<std::pair<void*, void*>, LockStack> lockorders;
-static boost::thread_specific_ptr<LockStack> lockstack;
-
-
-static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
-{
- printf("POTENTIAL DEADLOCK DETECTED\n");
- printf("Previous lock order was:\n");
- BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
- {
- if (i.first == mismatch.first) printf(" (1)");
- if (i.first == mismatch.second) printf(" (2)");
- printf(" %s\n", i.second.ToString().c_str());
- }
- printf("Current lock order is:\n");
- BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
- {
- if (i.first == mismatch.first) printf(" (1)");
- if (i.first == mismatch.second) printf(" (2)");
- printf(" %s\n", i.second.ToString().c_str());
- }
-}
-
-static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
-{
- bool fOrderOK = true;
- if (lockstack.get() == NULL)
- lockstack.reset(new LockStack);
-
- if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
- dd_mutex.lock();
-
- (*lockstack).push_back(std::make_pair(c, locklocation));
-
- if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
- {
- if (i.first == c) break;
-
- std::pair<void*, void*> p1 = std::make_pair(i.first, c);
- if (lockorders.count(p1))
- continue;
- lockorders[p1] = (*lockstack);
-
- std::pair<void*, void*> p2 = std::make_pair(c, i.first);
- if (lockorders.count(p2))
- {
- potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
- break;
- }
- }
- dd_mutex.unlock();
-}
-
-static void pop_lock()
-{
- if (fDebug)
- {
- const CLockLocation& locklocation = (*lockstack).rbegin()->second;
- printf("Unlocked: %s\n", locklocation.ToString().c_str());
- }
- dd_mutex.lock();
- (*lockstack).pop_back();
- dd_mutex.unlock();
-}
-
-void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
-{
- push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
-}
-
-void LeaveCritical()
-{
- pop_lock();
-}
-
-#endif /* DEBUG_LOCKORDER */