diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index ea3f4541ca..5ab7de86ab 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -40,9 +40,6 @@ //M*/ #include "precomp.hpp" -#include "opencv2/imgproc.hpp" - -using namespace cv; #ifndef _WIN32 @@ -66,6 +63,11 @@ using namespace cv; #include #endif +#include +#include "opencv2/imgproc.hpp" + +using namespace cv; + #ifndef BIT_ALLIN #define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) ) #endif @@ -595,10 +597,15 @@ int thread_started=0; static gpointer icvWindowThreadLoop(gpointer data); GMutex* last_key_mutex = NULL; GCond* cond_have_key = NULL; -GMutex* window_mutex = NULL; GThread* window_thread = NULL; #endif +static cv::Mutex& getWindowMutex() +{ + static cv::Mutex* g_window_mutex = new cv::Mutex(); + return *g_window_mutex; +} + static int last_key = -1; static std::vector< Ptr > g_windows; @@ -625,28 +632,28 @@ CV_IMPL int cvInitSystem( int argc, char** argv ) CV_IMPL int cvStartWindowThread(){ #ifdef HAVE_GTHREAD cvInitSystem(0,NULL); - if (!thread_started) { - if (!g_thread_supported ()) { - /* the GThread system wasn't inited, so init it */ - g_thread_init(NULL); - } + if (!thread_started) + { + if (!g_thread_supported ()) { + /* the GThread system wasn't inited, so init it */ + g_thread_init(NULL); + } - // this mutex protects the window resources - window_mutex = g_mutex_new(); + (void)getWindowMutex(); // force mutex initialization - // protects the 'last key pressed' variable - last_key_mutex = g_mutex_new(); + // protects the 'last key pressed' variable + last_key_mutex = g_mutex_new(); - // conditional that indicates a key has been pressed - cond_have_key = g_cond_new(); + // conditional that indicates a key has been pressed + cond_have_key = g_cond_new(); -#if !GLIB_CHECK_VERSION(2, 32, 0) - // this is the window update thread - window_thread = g_thread_create(icvWindowThreadLoop, - NULL, TRUE, NULL); -#else - window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); -#endif + #if !GLIB_CHECK_VERSION(2, 32, 0) + // this is the window update thread + window_thread = g_thread_create(icvWindowThreadLoop, + NULL, TRUE, NULL); + #else + window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); + #endif } thread_started = window_thread!=NULL; return thread_started; @@ -659,9 +666,10 @@ CV_IMPL int cvStartWindowThread(){ gpointer icvWindowThreadLoop(gpointer /*data*/) { while(1){ - g_mutex_lock(window_mutex); - gtk_main_iteration_do(FALSE); - g_mutex_unlock(window_mutex); + { + cv::AutoLock lock(getWindowMutex()); + gtk_main_iteration_do(FALSE); + } // little sleep g_usleep(500); @@ -671,20 +679,10 @@ gpointer icvWindowThreadLoop(gpointer /*data*/) return NULL; } - -class GMutexLock { - GMutex* mutex_; -public: - GMutexLock(GMutex* mutex) : mutex_(mutex) { if (mutex_) g_mutex_lock(mutex_); } - ~GMutexLock() { if (mutex_) g_mutex_unlock(mutex_); mutex_ = NULL; } -}; - -#define CV_LOCK_MUTEX() GMutexLock lock(window_mutex); - -#else -#define CV_LOCK_MUTEX() #endif +#define CV_LOCK_MUTEX() cv::AutoLock lock(getWindowMutex()) + static CvWindow* icvFindWindowByName( const char* name ) { for(size_t i = 0; i < g_windows.size(); ++i) @@ -1705,18 +1703,19 @@ static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer us code |= event->state << 16; #ifdef HAVE_GTHREAD - if(thread_started) g_mutex_lock(last_key_mutex); -#endif - - last_key = code; - -#ifdef HAVE_GTHREAD - if(thread_started){ + if(thread_started) + { + g_mutex_lock(last_key_mutex); + last_key = code; // signal any waiting threads g_cond_broadcast(cond_have_key); g_mutex_unlock(last_key_mutex); } + else #endif + { + last_key = code; + } return FALSE; } @@ -1886,10 +1885,12 @@ static gboolean icvAlarm( gpointer user_data ) CV_IMPL int cvWaitKey( int delay ) { #ifdef HAVE_GTHREAD - if(thread_started && g_thread_self()!=window_thread){ - gboolean expired; + if (thread_started && g_thread_self() != window_thread) + { + gboolean expired = true; int my_last_key; + g_mutex_lock(last_key_mutex); // wait for signal or timeout if delay > 0 if(delay>0){ GTimeVal timer; @@ -1898,8 +1899,15 @@ CV_IMPL int cvWaitKey( int delay ) expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer); } else{ - g_cond_wait(cond_have_key, last_key_mutex); - expired=false; + if (g_windows.empty()) + { + CV_LOG_WARNING(NULL, "cv::waitKey() is called without timeout and missing active windows. Ignoring"); + } + else + { + g_cond_wait(cond_have_key, last_key_mutex); + expired=false; + } } my_last_key = last_key; g_mutex_unlock(last_key_mutex); @@ -1908,21 +1916,20 @@ CV_IMPL int cvWaitKey( int delay ) } return my_last_key; } - else{ + else #endif + { int expired = 0; guint timer = 0; if( delay > 0 ) timer = g_timeout_add( delay, icvAlarm, &expired ); last_key = -1; - while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && !g_windows.empty()) + while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && (delay > 0 || !g_windows.empty())) ; if( delay > 0 && !expired ) g_source_remove(timer); -#ifdef HAVE_GTHREAD } -#endif return last_key; }