bool          m_closed;           // was the other end closed?
   wxUint32      m_lcount;           // last IO transaction size
   unsigned long m_timeout;          // IO timeout value in seconds
-  wxList        m_states;           // stack of states
+                                    // (TODO: remove, wxSocketImpl has it too)
+  wxList        m_states;           // stack of states (TODO: remove!)
   bool          m_interrupt;        // interrupt ongoing wait operations?
   bool          m_beingDeleted;     // marked for delayed deletion?
   wxIPV4address m_localAddress;     // bind to local address?
   wxSocketEventFlags  m_eventmask;  // which events to notify?
   wxSocketEventFlags  m_eventsgot;  // collects events received in OnRequest()
 
-  // the initialization count, GSocket is initialized if > 0
+  // the initialization count, wxSocket is initialized if > 0
   static size_t m_countInit;
 
+
+  friend class wxSocketReadGuard;
+  friend class wxSocketWriteGuard;
+
   DECLARE_NO_COPY_CLASS(wxSocketBase)
   DECLARE_CLASS(wxSocketBase)
 };
 
     DECLARE_NO_COPY_CLASS(wxSocketState)
 };
 
+// wxSocketWaitModeChanger: temporarily change the socket flags affecting its
+// wait mode
+class wxSocketWaitModeChanger
+{
+public:
+    // temporarily set the flags to include the flag value which may be either
+    // wxSOCKET_NOWAIT or wxSOCKET_WAITALL
+    wxSocketWaitModeChanger(wxSocketBase *socket, int flag)
+        : m_socket(socket),
+          m_oldflags(socket->GetFlags())
+
+    {
+        wxASSERT_MSG( flag == wxSOCKET_WAITALL || flag == wxSOCKET_NOWAIT,
+                      "not a wait flag" );
+
+        // preserve wxSOCKET_BLOCK value when switching to wxSOCKET_WAITALL
+        // mode but not when switching to wxSOCKET_NOWAIT as the latter is
+        // incompatible with wxSOCKET_BLOCK
+        if ( flag != wxSOCKET_NOWAIT )
+            flag |= m_oldflags & wxSOCKET_BLOCK;
+
+        socket->SetFlags(flag);
+    }
+
+    ~wxSocketWaitModeChanger()
+    {
+        m_socket->SetFlags(m_oldflags);
+    }
+
+private:
+    wxSocketBase * const m_socket;
+    const int m_oldflags;
+
+    DECLARE_NO_COPY_CLASS(wxSocketWaitModeChanger)
+};
+
+// wxSocketRead/WriteGuard are instantiated before starting reading
+// from/writing to the socket
+class wxSocketReadGuard
+{
+public:
+    wxSocketReadGuard(wxSocketBase *socket)
+        : m_socket(socket)
+    {
+        wxASSERT_MSG( !m_socket->m_reading, "read reentrancy?" );
+
+        m_socket->m_reading = true;
+    }
+
+    ~wxSocketReadGuard()
+    {
+        m_socket->m_reading = false;
+    }
+
+private:
+    wxSocketBase * const m_socket;
+
+    DECLARE_NO_COPY_CLASS(wxSocketReadGuard)
+};
+
+class wxSocketWriteGuard
+{
+public:
+    wxSocketWriteGuard(wxSocketBase *socket)
+        : m_socket(socket)
+    {
+        wxASSERT_MSG( !m_socket->m_writing, "write reentrancy?" );
+
+        m_socket->m_writing = true;
+    }
+
+    ~wxSocketWriteGuard()
+    {
+        m_socket->m_writing = false;
+    }
+
+private:
+    wxSocketBase * const m_socket;
+
+    DECLARE_NO_COPY_CLASS(wxSocketWriteGuard)
+};
+
 // ============================================================================
 // wxSocketManager
 // ============================================================================
 
 void wxSocketBase::Init()
 {
-    m_impl       = NULL;
+    m_impl         = NULL;
     m_type         = wxSOCKET_UNINIT;
 
     // state
 
 wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
 {
-    // Mask read events
-    m_reading = true;
+    wxSocketReadGuard read(this);
 
     m_lcount = DoRead(buffer, nbytes);
 
-    // Allow read events from now on
-    m_reading = false;
-
     return *this;
 }
 
         unsigned char len[4];
     } msg;
 
-    // Mask read events
-    m_reading = true;
+    wxSocketReadGuard read(this);
 
-    int old_flags = m_flags;
-    SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
+    wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
 
     bool ok = false;
     if ( DoRead(&msg, sizeof(msg)) == sizeof(msg) )
     if ( !ok )
         SetError(wxSOCKET_IOERR);
 
-    m_reading = false;
-    SetFlags(old_flags);
-
     return *this;
 }
 
 wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
 {
-    // Mask read events
-    m_reading = true;
+    wxSocketReadGuard read(this);
 
     m_lcount = DoRead(buffer, nbytes);
-    Pushback(buffer, m_lcount);
 
-    // Allow read events again
-    m_reading = false;
+    Pushback(buffer, m_lcount);
 
     return *this;
 }
 
 wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
 {
-    // Mask write events
-    m_writing = true;
+    wxSocketWriteGuard write(this);
 
     m_lcount = DoWrite(buffer, nbytes);
 
-    // Allow write events again
-    m_writing = false;
-
     return *this;
 }
 
         unsigned char len[4];
     } msg;
 
-    // Mask write events
-    m_writing = true;
+    wxSocketWriteGuard write(this);
 
-    const int old_flags = m_flags;
-    SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
+    wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
 
     msg.sig[0] = (unsigned char) 0xad;
     msg.sig[1] = (unsigned char) 0xde;
     if ( !ok )
         SetError(wxSOCKET_IOERR);
 
-    m_writing = false;
-    SetFlags(old_flags);
-
     return *this;
 }
 
     wxUint32 ret;
     wxUint32 total = 0;
 
-    // Mask read events
-    m_reading = true;
+    wxSocketReadGuard read(this);
 
-    const int old_flags = m_flags;
-    SetFlags(wxSOCKET_NOWAIT);
+    wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
 
     do
     {
     m_lcount = total;
     SetError(wxSOCKET_NOERROR);
 
-    // Allow read events again
-    m_reading = false;
-
-    SetFlags(old_flags);
-
     return *this;
 }