Does boost::threads + wine threads == happiness? I would like to use boost threads in my winelib application, but they need to coexist with threads created using the windows APIs by 3rd party plugin DLLs. I built a test app that uses the two and they appear to share both a CRITICAL_SECTION and a boost::mutex fine, so it looks like I am in the clear. But I don't have alot of confidence in my understanding of how Wine implements threads, so I thought it would be wise to ask. Attached is my test program. To build and run: $ wineg++ -c boost-win.cpp $ wineg++ -o boost-win.exe.so boost-win.o -lboost_threads $ wine ./boost-win.exe.so Cheers... mo PS: thanks to whoever is responsible for wineg++. What a timesaver! boost-win.cpp: #include "boost/thread.hpp" #include <pthread.h> // pthread_create #include <sys/resource.h> // PRIO_PROCESS #include <stdio.h> // printf #include <windows.h> // CreateThread #define INDENT " " DWORD WINAPI CSTestA(void* arg) { CRITICAL_SECTION* cs = (CRITICAL_SECTION*) arg; puts("in, try CS"); ::EnterCriticalSection(cs); puts("CS locked"); sleep(2); puts("wake up"); ::LeaveCriticalSection(cs); puts("unlock"); sleep(1); puts("wake up, try CS"); ::EnterCriticalSection(cs); puts("CS locked"); sleep(1); puts("wake up"); ::LeaveCriticalSection(cs); puts("unlock"); puts("out"); } struct CSTestB { CSTestB(CRITICAL_SECTION* cs) : m_criticalSection(cs) { } void operator()() { puts(INDENT "in, try CS"); ::EnterCriticalSection(m_criticalSection); puts(INDENT "CS locked"); boost::xtime t; boost::xtime_get(&t, boost::TIME_UTC); t.sec += 3; boost::thread::sleep(t); puts(INDENT"wake up"); ::LeaveCriticalSection(m_criticalSection); puts(INDENT "unlocked, out"); boost::xtime_get(&t, boost::TIME_UTC); t.sec += 3; boost::thread::sleep(t); puts(INDENT "out"); } CRITICAL_SECTION* m_criticalSection; }; struct MutexTestA { MutexTestA(boost::mutex* mutex) : m_mutex(mutex) { } void operator()() { puts("in - try mutex"); boost::xtime t; { // scope boost::mutex::scoped_lock lock(*m_mutex); puts("mutex locked"); boost::xtime_get(&t, boost::TIME_UTC); t.sec += 2; boost::thread::sleep(t); puts("wake up"); } puts("unlock"); boost::xtime_get(&t, boost::TIME_UTC); t.sec += 1; boost::thread::sleep(t); puts("wake up, try mutex"); { // scope boost::mutex::scoped_lock lock(*m_mutex); puts("mutex locked"); boost::xtime_get(&t, boost::TIME_UTC); t.sec += 1; boost::thread::sleep(t); puts("wake up"); } puts("unlock"); puts("out"); } boost::mutex* m_mutex; }; DWORD WINAPI MutexTestB(void* arg) { boost::mutex* mutex = (boost::mutex*) arg; puts(INDENT "in - try mutex"); { // scope boost::mutex::scoped_lock lock(*mutex); puts(INDENT "mutex locked"); boost::xtime t; boost::xtime_get(&t, boost::TIME_UTC); t.sec += 3; boost::thread::sleep(t); puts(INDENT "wake up"); } puts(INDENT "unlock"); puts(INDENT "out"); } int main(int argc, char *argv[]) { // boost blocks on CS held by winthread if (argc > 1 && memcmp(argv[1], "cs", 2) == 0) { puts("Testing CRITICAL_SECTIONS...\n"); puts(" winThread and boostThread share a CRITICAL_SECTION. winThread grabs"); puts(" it and sleeps, while boostThread waits for winThread to wake up and"); puts(" release. Then vice-versa."); puts(""); puts("winThread boostThread"); puts("----------------------------------"); CRITICAL_SECTION* criticalSection = new CRITICAL_SECTION(); ::InitializeCriticalSection(criticalSection); DWORD junk; HANDLE winThread = ::CreateThread(NULL, 0, CSTestA, criticalSection, 0, &junk); // delay 'cause boost starts faster sleep(1); CSTestB boostTest(criticalSection); boost::thread boostThread(boostTest); boostThread.join(); // todo: howto wait for winThread? ::DeleteCriticalSection(criticalSection); delete(criticalSection); } else if (argc > 1 && memcmp(argv[1], "mu", 2) == 0) { puts("Testing boost::mutex...\n"); puts(" winThread and boostThread share a boost::mutex. boostThread grabs"); puts(" it and sleeps, while winThread waits for boostThread to wake up and"); puts(" release. Then vice-versa."); puts(""); puts("boostThread winThread"); puts("----------------------------------"); boost::mutex mutex; MutexTestA testA(&mutex); boost::thread boostThread(testA); DWORD junk; HANDLE winThread = ::CreateThread(NULL, 0, MutexTestB, &mutex, 0, &junk); boostThread.join(); // todo: howto wait for winThread? } else { puts("usage: boost-win [boostcs]"); puts("options:"); puts(" cs - see if boost and win threads can both honor a CRITICAL_SECTION"); return 1; } return 0; }
participants (1)
-
Michael Ost