+// ============================================================================
+// GSocketManager
+// ============================================================================
+
+GSocketManager *GSocketManager::ms_manager = NULL;
+
+/* static */
+void GSocketManager::Set(GSocketManager *manager)
+{
+ wxASSERT_MSG( !ms_manager, "too late to set manager now" );
+
+ ms_manager = manager;
+}
+
+/* static */
+void GSocketManager::Init()
+{
+ wxASSERT_MSG( !ms_manager, "shouldn't be initialized twice" );
+
+ /*
+ Details: Initialize() creates a hidden window as a sink for socket
+ events, such as 'read completed'. wxMSW has only one message loop
+ for the main thread. If Initialize is called in a secondary thread,
+ the socket window will be created for the secondary thread, but
+ since there is no message loop on this thread, it will never
+ receive events and all socket operations will time out.
+ BTW, the main thread must not be stopped using sleep or block
+ on a semaphore (a bad idea in any case) or socket operations
+ will time out.
+
+ On the Mac side, Initialize() stores a pointer to the CFRunLoop for
+ the main thread. Because secondary threads do not have run loops,
+ adding event notifications to the "Current" loop would have no
+ effect at all, events would never fire.
+ */
+ wxASSERT_MSG( wxIsMainThread(),
+ "sockets must be initialized from the main thread" );
+
+ wxAppConsole * const app = wxAppConsole::GetInstance();
+ wxCHECK_RET( app, "sockets can't be initialized without wxApp" );
+
+ ms_manager = app->GetTraits()->GetSocketManager();
+}
+