00001 /* 00002 * synergy -- mouse and keyboard sharing utility 00003 * Copyright (C) 2004 Chris Schoeneman 00004 * 00005 * This package is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * found in the file COPYING that should have accompanied this file. 00008 * 00009 * This package is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 */ 00014 00015 #ifndef CSOCKETMULTIPLEXER_H 00016 #define CSOCKETMULTIPLEXER_H 00017 00018 #include "IArchNetwork.h" 00019 #include "stdlist.h" 00020 #include "stdmap.h" 00021 00022 template <class T> 00023 class CCondVar; 00024 class CMutex; 00025 class CThread; 00026 class ISocket; 00027 class ISocketMultiplexerJob; 00028 00030 00033 class CSocketMultiplexer { 00034 public: 00035 CSocketMultiplexer(); 00036 ~CSocketMultiplexer(); 00037 00039 00040 00041 void addSocket(ISocket*, ISocketMultiplexerJob*); 00042 00043 void removeSocket(ISocket*); 00044 00046 00047 00048 00049 // maybe belongs on ISocketMultiplexer 00050 static CSocketMultiplexer* 00051 getInstance(); 00052 00054 00055 private: 00056 // list of jobs. we use a list so we can safely iterate over it 00057 // while other threads modify it. 00058 typedef std::list<ISocketMultiplexerJob*> CSocketJobs; 00059 typedef CSocketJobs::iterator CJobCursor; 00060 typedef std::map<ISocket*, CJobCursor> CSocketJobMap; 00061 00062 // service sockets. the service thread will only access m_sockets 00063 // and m_update while m_pollable and m_polling are true. all other 00064 // threads must only modify these when m_pollable and m_polling are 00065 // false. only the service thread sets m_polling. 00066 void serviceThread(void*); 00067 00068 // create, iterate, and destroy a cursor. a cursor is used to 00069 // safely iterate through the job list while other threads modify 00070 // the list. it works by inserting a dummy item in the list and 00071 // moving that item through the list. the dummy item will never 00072 // be removed by other edits so an iterator pointing at the item 00073 // remains valid until we remove the dummy item in deleteCursor(). 00074 // nextCursor() finds the next non-dummy item, moves our dummy 00075 // item just past it, and returns an iterator for the non-dummy 00076 // item. all cursor calls lock the mutex for their duration. 00077 CJobCursor newCursor(); 00078 CJobCursor nextCursor(CJobCursor); 00079 void deleteCursor(CJobCursor); 00080 00081 // lock out locking the job list. this blocks if another thread 00082 // has already locked out locking. once it returns, only the 00083 // calling thread will be able to lock the job list after any 00084 // current lock is released. 00085 void lockJobListLock(); 00086 00087 // lock the job list. this blocks if the job list is already 00088 // locked. the calling thread must have called requestJobLock. 00089 void lockJobList(); 00090 00091 // unlock the job list and the lock out on locking. 00092 void unlockJobList(); 00093 00094 private: 00095 CMutex* m_mutex; 00096 CThread* m_thread; 00097 bool m_update; 00098 CCondVar<bool>* m_jobsReady; 00099 CCondVar<bool>* m_jobListLock; 00100 CCondVar<bool>* m_jobListLockLocked; 00101 CThread* m_jobListLocker; 00102 CThread* m_jobListLockLocker; 00103 00104 CSocketJobs m_socketJobs; 00105 CSocketJobMap m_socketJobMap; 00106 ISocketMultiplexerJob* m_cursorMark; 00107 00108 static CSocketMultiplexer* s_instance; 00109 }; 00110 00111 #endif