Calling Initialize() from another thread could never work before but it wasn't
clear that this was the case so document it in the functions comments and
documentation now and add asserts checking that they are called from the main
thread only.
Also simplify the code as we don't actually need to do any reference-counting
here and a simple boolean flag indicating whether the sockets are initialized
is enough.
Closes #11119.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61985
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
void SetNotify(wxSocketEventFlags flags);
void Notify(bool notify);
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();
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
// --------------------------
// Implementation from now on
// --------------------------
wxSocketEventFlags m_eventmask; // which events to notify?
wxSocketEventFlags m_eventsgot; // collects events received in OnRequest()
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;
friend class wxSocketReadGuard;
friend class wxSocketWriteGuard;
does anything) but you must call Shutdown() exactly once for every call
to Initialize().
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.
@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 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();
*/
static void Shutdown();
// Initialization and 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()
{
bool wxSocketBase::IsInitialized()
{
- return m_countInit > 0;
+ wxASSERT_MSG( wxIsMainThread(), "unsafe to call from other threads" );
+
+ return gs_socketInitDone;
}
bool wxSocketBase::Initialize()
{
}
bool wxSocketBase::Initialize()
{
+ wxCHECK_MSG( wxIsMainThread(), false,
+ "must be called from the main thread" );
+
+ if ( !gs_socketInitDone )
{
wxSocketManager * const manager = wxSocketManager::Get();
if ( !manager || !manager->OnInit() )
{
wxSocketManager * const manager = wxSocketManager::Get();
if ( !manager || !manager->OnInit() )
+
+ gs_socketInitDone = true;
void wxSocketBase::Shutdown()
{
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" );
+ 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;
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())
- wxLogError("Cannot initialize wxSocketBase");
+ wxLogError(_("Cannot initialize sockets"));