void SetNotify(wxSocketEventFlags flags);
void Notify(bool notify);
- // initialize/shutdown the sockets (usually called automatically)
- static bool IsInitialized();
+ // initialize/shutdown the sockets (done automatically so there is no need
+ // to call these functions usually)
+ //
+ // should always be called from the main thread only so one of the cases
+ // where they should indeed be called explicitly is when the first wxSocket
+ // object in the application is created in a different thread
static bool Initialize();
static void Shutdown();
+ // check if wxSocket had been already initialized
+ //
+ // notice that this function should be only called from the main thread as
+ // otherwise it is inherently unsafe because Initialize/Shutdown() may be
+ // called concurrently with it in the main thread
+ static bool IsInitialized();
// Implementation from now on
// --------------------------
wxSocketEventFlags m_eventmask; // which events to notify?
wxSocketEventFlags m_eventsgot; // collects events received in OnRequest()
- // the initialization count, wxSocket is initialized if > 0
- static size_t m_countInit;
-
friend class wxSocketReadGuard;
friend class wxSocketWriteGuard;
does anything) but you must call Shutdown() exactly once for every call
to Initialize().
+ This function should only be called from the main thread.
+
@return
@true if the sockets can be used, @false if the initialization
failed and sockets are not available at all.
This function undoes the call to Initialize() and must be called after
every successful call to Initialize().
+
+ This function should only be called from the main thread, just as
+ Initialize().
*/
static void Shutdown();
// Initialization and shutdown
// --------------------------------------------------------------------------
-// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
-// to m_countInit with a crit section
-size_t wxSocketBase::m_countInit = 0;
+namespace
+{
+
+// flag indicating whether wxSocketManager was already initialized
+bool gs_socketInitDone = false;
+
+} // anonymous namespace
bool wxSocketBase::IsInitialized()
{
- return m_countInit > 0;
+ wxASSERT_MSG( wxIsMainThread(), "unsafe to call from other threads" );
+
+ return gs_socketInitDone;
}
bool wxSocketBase::Initialize()
{
- if ( !m_countInit++ )
+ wxCHECK_MSG( wxIsMainThread(), false,
+ "must be called from the main thread" );
+
+ if ( !gs_socketInitDone )
{
wxSocketManager * const manager = wxSocketManager::Get();
if ( !manager || !manager->OnInit() )
- {
- m_countInit--;
-
return false;
- }
+
+ gs_socketInitDone = true;
}
return true;
void wxSocketBase::Shutdown()
{
- // we should be initialized
- wxASSERT_MSG( m_countInit > 0, wxT("extra call to Shutdown()") );
- if ( --m_countInit == 0 )
- {
- wxSocketManager * const manager = wxSocketManager::Get();
- wxCHECK_RET( manager, "should have a socket manager" );
+ wxCHECK_RET( wxIsMainThread(), "must be called from the main thread" );
- manager->OnExit();
- }
+ wxCHECK_RET( gs_socketInitDone, "unnecessary call to Shutdown()" );
+
+ gs_socketInitDone = false;
+
+ wxSocketManager * const manager = wxSocketManager::Get();
+ wxCHECK_RET( manager, "should have a socket manager" );
+
+ manager->OnExit();
}
// --------------------------------------------------------------------------
m_eventmask =
m_eventsgot = 0;
- if ( !IsInitialized() )
+ // when we create the first socket in the main thread we initialize the
+ // OS-dependent socket stuff: notice that this means that the user code
+ // needs to call wxSocket::Initialize() itself if the first socket it
+ // creates is not created in the main thread
+ if ( wxIsMainThread() )
{
- // this Initialize() will be undone by wxSocketModule::OnExit(), all
- // the other calls to it should be matched by a call to Shutdown()
- if (!Initialize())
+ if ( !Initialize() )
{
- wxLogError("Cannot initialize wxSocketBase");
+ wxLogError(_("Cannot initialize sockets"));
}
}
}