wvwinstreamclone.cc

00001 
00002 #include "wvwinstreamclone.h"
00003 
00004 ATOM WvWinStreamClone::s_aClass = 0;
00005 WvWinStreamClone::WndVector WvWinStreamClone::s_wndpool;
00006 WvWinStreamClone::WndStreamMap WvWinStreamClone::s_wndmap;
00007 
00008 HWND WvWinStreamClone::alloc_wnd()
00009 {
00010     if (s_wndpool.empty())
00011     {
00012         HWND hWnd = CreateWindow(
00013             "WvWinStreamClone",
00014             "WvWinStreamWindowName",
00015             WS_POPUP | WS_DISABLED,
00016             CW_USEDEFAULT, // initial x position
00017             CW_USEDEFAULT, // initial y position
00018             CW_USEDEFAULT, // initial x extent
00019             CW_USEDEFAULT, // initial y extent
00020             HWND_MESSAGE,
00021             NULL,
00022             NULL,
00023             NULL
00024         );
00025         assert(hWnd);
00026         s_wndpool.push_back(hWnd);
00027     }
00028 
00029     HWND hWnd = s_wndpool.back();
00030     s_wndpool.pop_back();
00031 
00032     // associate window with this instance
00033     s_wndmap[hWnd] = this;
00034 
00035     return hWnd;
00036 }
00037 
00038 void WvWinStreamClone::free_wnd(HWND w)
00039 {
00040     s_wndpool.push_back(w);
00041 }
00042 
00043 DWORD WvWinStreamClone::Initialize()
00044 {
00045     WNDCLASS wc;
00046     wc.style = CS_HREDRAW | CS_VREDRAW;
00047     wc.lpfnWndProc = WvWinStreamClone::WndProc;
00048     wc.cbClsExtra = 0;
00049     wc.cbWndExtra = 0;
00050     wc.hInstance = GetModuleHandle(NULL);
00051     wc.hIcon = NULL; 
00052     wc.hCursor = NULL;
00053     wc.hbrBackground = NULL; 
00054     wc.lpszMenuName = NULL;
00055     wc.lpszClassName = "WvWinStreamClone";
00056 
00057     s_aClass = RegisterClass(&wc);
00058     if (!s_aClass)
00059     {
00060         DWORD error = GetLastError();
00061         return error;
00062     }
00063     return 0;
00064 }
00065 
00066 WvWinStreamClone::WvWinStreamClone(WvStream * _cloned) :
00067     WvStreamClone(_cloned), m_pending_callback(false), m_select_in_progress(false),
00068     m_msec_timeout(500)
00069 {
00070     memset(&m_si, 0, sizeof(m_si));
00071     m_hWnd = alloc_wnd();
00072     pre_poll();
00073 }
00074 
00075 WvWinStreamClone::~WvWinStreamClone()
00076 {
00077     free_wnd(m_hWnd);
00078 }
00079 
00080 // for each socket in "set", add the "event" to the its associated mask in sockmap 
00081 void WvWinStreamClone::select_set(SocketEventsMap &sockmap, fd_set *set, long event )
00082 {
00083     for (unsigned i=0; i<set->fd_count; i++)
00084     {
00085         SOCKET &socket = set->fd_array[i];
00086         sockmap[socket] |= event;
00087     }
00088 
00089     FD_ZERO(set);
00090 }
00091 
00092 void WvWinStreamClone::pre_poll()
00093 {
00094     bool sure = this->_build_selectinfo(m_si, m_msec_timeout, 
00095                                         false, false, false, true);
00096     
00097     if (sure)
00098     {
00099         m_pending_callback = true;
00100         m_si.msec_timeout = 0;
00101     }
00102 
00103     // We must only call WSAAsyncSelect once per socket, so we need
00104     // to collect all the events from each set first, grouping them by
00105     // socket rather than by event
00106     SocketEventsMap sockmap;
00107     this->select_set(sockmap, &m_si.read, FD_READ);
00108     this->select_set(sockmap, &m_si.write, FD_WRITE);
00109     this->select_set(sockmap, &m_si.except, FD_OOB);
00110 
00111     // Call WSAAsyncSelect, asking the OS to send us a message when the socket
00112     // becomes readable | writable | exceptional
00113     for (SocketEventsMap::iterator i = sockmap.begin(); i!=sockmap.end(); ++i)
00114     {
00115         SOCKET socket = (*i).first;
00116         long events = (*i).second;
00117         
00118         int result = ::WSAAsyncSelect(socket, m_hWnd, WM_SELECT, 
00119                                       events | FD_CONNECT | FD_CLOSE | FD_ACCEPT);
00120         assert(result == 0);
00121     }
00122 
00123     // alarm
00124     ::KillTimer(m_hWnd, TIMER_ID);
00125     if (m_si.msec_timeout >= 0)
00126     {
00127         ::SetTimer(m_hWnd, TIMER_ID, m_si.msec_timeout, NULL);
00128     }
00129 
00130     m_select_in_progress = true;
00131 }
00132 
00133 void WvWinStreamClone::post_poll()
00134 {
00135     bool sure = this->_process_selectinfo(m_si, true);
00136     
00137     if (sure || m_pending_callback)
00138     {
00139         m_pending_callback = false;
00140         callback();
00141         if (globalstream) globalstream->callback();
00142     }
00143 }
00144 
00145 void WvWinStreamClone::select_callback(SOCKET socket, int events, int error)
00146 {
00147     if (events | FD_READ) FD_SET(socket, &m_si.read);
00148     if (events | FD_WRITE) FD_SET(socket, &m_si.write);
00149     if (events | FD_OOB) FD_SET(socket, &m_si.except);
00150     m_pending_callback = true;
00151 
00152     if (m_select_in_progress)
00153     {
00154         ::PostMessage(m_hWnd, WM_DONESELECT, 0, 0);
00155         m_select_in_progress = false;
00156     }
00157 }
00158 
00159 LRESULT CALLBACK WvWinStreamClone::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00160 {
00161     switch (uMsg)
00162     {
00163     case WM_DONESELECT:
00164     {   
00165         WvWinStreamClone *_this = s_wndmap[hwnd];
00166         assert(_this);
00167         _this->post_poll();
00168         _this->pre_poll();
00169         
00170         break;
00171     }
00172 
00173     case WM_SELECT:
00174     {
00175         WvWinStreamClone *_this = s_wndmap[hwnd];       
00176         assert(_this);
00177         SOCKET socket = wParam;
00178         int events = WSAGETSELECTEVENT(lParam);
00179         int error = WSAGETSELECTERROR(lParam);
00180         _this->select_callback( socket, events, error );
00181         
00182         break;
00183     }
00184 
00185     case WM_TIMER:
00186     {
00187         ::PostMessage(hwnd, WM_DONESELECT, 0, 0);
00188 
00189         break;
00190     }
00191 
00192     default:
00193         return DefWindowProc(hwnd, uMsg, wParam, lParam);
00194     }
00195     return 0;
00196 }

Generated on Wed Jul 12 17:53:22 2006 for WvStreams by  doxygen 1.4.7