mirror of
https://github.com/debauchee/barrier.git
synced 2026-02-13 15:15:21 +08:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
210c2b70bd | ||
|
|
8320686e0d | ||
|
|
90f7a68695 | ||
|
|
0ed18c6b89 | ||
|
|
69a65e4725 | ||
|
|
4dddbb5816 | ||
|
|
894191d1cb | ||
|
|
f791a482b9 | ||
|
|
0ed9451430 | ||
|
|
28466eea10 | ||
|
|
1bdc95a498 | ||
|
|
f1c570752b | ||
|
|
70a4ece9e8 | ||
|
|
58f6c735ff | ||
|
|
fca05b9163 | ||
|
|
7bb541ea91 | ||
|
|
ccfa10f2a0 | ||
|
|
5812030f43 | ||
|
|
e31ebc1b22 | ||
|
|
69ea670c1f | ||
|
|
3600f4b255 | ||
|
|
4ec30b6ade | ||
|
|
452820eef7 | ||
|
|
c685f0f231 | ||
|
|
cf3b86341a | ||
|
|
6c88843771 | ||
|
|
dea143bfd7 | ||
|
|
dcc45dd80e | ||
|
|
7bcb74adc1 | ||
|
|
e9f6092172 | ||
|
|
b0e415de03 | ||
|
|
83d0639230 | ||
|
|
93c04bb2fa | ||
|
|
36f3235f51 | ||
|
|
d9d39040ae | ||
|
|
9df4741748 | ||
|
|
f71c68506e | ||
|
|
a841b2858f | ||
|
|
8dd6bc2c55 | ||
|
|
0cd2e6bb6c | ||
|
|
00c18b4c92 | ||
|
|
9f15b1bcf2 | ||
|
|
71f2ca7c35 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,3 +31,4 @@ CMakeCache.txt
|
|||||||
.vscode/
|
.vscode/
|
||||||
# Transient in-project-directory dependencies
|
# Transient in-project-directory dependencies
|
||||||
/deps/
|
/deps/
|
||||||
|
/out/build/x64-Debug
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
#
|
#
|
||||||
BARRIER_VERSION_MAJOR = 2
|
BARRIER_VERSION_MAJOR = 2
|
||||||
BARRIER_VERSION_MINOR = 3
|
BARRIER_VERSION_MINOR = 3
|
||||||
BARRIER_VERSION_PATCH = 1
|
BARRIER_VERSION_PATCH = 2
|
||||||
BARRIER_VERSION_STAGE = snapshot
|
BARRIER_VERSION_STAGE = snapshot
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ include_directories (BEFORE SYSTEM ./ext/gtest/include)
|
|||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
set (CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# For config.h, detect the libraries, functions, etc.
|
# For config.h, detect the libraries, functions, etc.
|
||||||
@@ -349,6 +349,12 @@ else()
|
|||||||
set (OPENSSL_LIBS ${lib_ssl} ${lib_crypto})
|
set (OPENSSL_LIBS ${lib_ssl} ${lib_crypto})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Check we have the *required* Qt5 libs.
|
||||||
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5Network REQUIRED)
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Configure_file... but for directories, recursively.
|
# Configure_file... but for directories, recursively.
|
||||||
#
|
#
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -1,7 +1,9 @@
|
|||||||
# Barrier
|
# Barrier
|
||||||
|
|
||||||
Eliminate the barrier between your machines.
|
Eliminate the barrier between your machines.
|
||||||
Find [releases here](https://github.com/debauchee/barrier/releases).
|
Find [releases for windows and macOS here](https://github.com/debauchee/barrier/releases).
|
||||||
|
Your distro probably already has barrier packaged for it, see [distro specific packages](#distro-specific-packages)
|
||||||
|
below for a list. Alternatively, we also provide a [flatpak](https://github.com/flathub/com.github.debauchee.barrier).
|
||||||
|
|
||||||
### Contact info:
|
### Contact info:
|
||||||
|
|
||||||
@@ -14,8 +16,9 @@ Master branch overall build status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
* Mac Build Status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
||||||
* Windows Debug Build Status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
* Windows Debug Build Status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
||||||
* Windows Release Build Status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
* Windows Release Build Status: [](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
|
||||||
|
* Snap: [](https://build.snapcraft.io/user/debauchee/barrier)
|
||||||
|
|
||||||
Our CI Builds are provided by Microsoft Azure Pipelines.
|
Our CI Builds are provided by Microsoft Azure Pipelines, Flathub, and Canonical.
|
||||||
|
|
||||||
### What is it?
|
### What is it?
|
||||||
|
|
||||||
@@ -43,6 +46,13 @@ For short and simple questions or to just say hello find us on the Freenode IRC
|
|||||||
|
|
||||||
At this time we are looking for developers to help fix the issues found in the issue tracker. Submit pull requests once you've polished up your patch and we'll review and possibly merge it.
|
At this time we are looking for developers to help fix the issues found in the issue tracker. Submit pull requests once you've polished up your patch and we'll review and possibly merge it.
|
||||||
|
|
||||||
|
## Distro specific packages
|
||||||
|
|
||||||
|
While not a comprehensive list, repology provides a decent list of distro
|
||||||
|
specific packages.
|
||||||
|
|
||||||
|
[](https://repology.org/project/barrier/versions)
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
Q: Does drag and drop work on linux?
|
Q: Does drag and drop work on linux?
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
set B_BUILD_TYPE=%CI_ENV_BUILD_TYPE%
|
set B_BUILD_TYPE=%CI_ENV_BUILD_TYPE%
|
||||||
set B_QT_ROOT=%cd%\deps\Qt
|
set B_QT_ROOT=%cd%\deps\Qt
|
||||||
set B_QT_VER=Qt5.12.3\5.12.3
|
set B_QT_VER=Qt5.13.0\5.13.0
|
||||||
set B_QT_MSVC=msvc2017_64
|
set B_QT_MSVC=msvc2017_64
|
||||||
set B_BONJOUR=%cd%\deps\BonjourSDKLike
|
set B_BONJOUR=%cd%\deps\BonjourSDKLike
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$qli_install_version = '2019.05.26.1'
|
$qli_install_version = '2019.05.26.1'
|
||||||
$qt_version = '5.12.3'
|
$qt_version = '5.13.0'
|
||||||
|
|
||||||
New-Item -Force -ItemType Directory -Path ".\deps\"
|
New-Item -Force -ItemType Directory -Path ".\deps\"
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ if exist bin\Debug (
|
|||||||
copy %B_QT_FULLPATH%\bin\Qt5Cored.dll bin\Debug\ > NUL
|
copy %B_QT_FULLPATH%\bin\Qt5Cored.dll bin\Debug\ > NUL
|
||||||
copy ..\ext\openssl\windows\x64\bin\* bin\Debug\ > NUL
|
copy ..\ext\openssl\windows\x64\bin\* bin\Debug\ > NUL
|
||||||
copy ..\res\openssl\barrier.conf bin\Debug\ > NUL
|
copy ..\res\openssl\barrier.conf bin\Debug\ > NUL
|
||||||
|
mkdir bin\Debug\platforms
|
||||||
|
copy %B_QT_FULLPATH%\plugins\platforms\qwindowsd.dll bin\Debug\platforms\ > NUL
|
||||||
) else if exist bin\Release (
|
) else if exist bin\Release (
|
||||||
copy %B_QT_FULLPATH%\bin\Qt5Core.dll bin\Release\ > NUL
|
copy %B_QT_FULLPATH%\bin\Qt5Core.dll bin\Release\ > NUL
|
||||||
copy %B_QT_FULLPATH%\bin\Qt5Gui.dll bin\Release\ > NUL
|
copy %B_QT_FULLPATH%\bin\Qt5Gui.dll bin\Release\ > NUL
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.4)
|
|||||||
|
|
||||||
set (BARRIER_VERSION_MAJOR 2)
|
set (BARRIER_VERSION_MAJOR 2)
|
||||||
set (BARRIER_VERSION_MINOR 3)
|
set (BARRIER_VERSION_MINOR 3)
|
||||||
set (BARRIER_VERSION_PATCH 1)
|
set (BARRIER_VERSION_PATCH 2)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Barrier Version
|
# Barrier Version
|
||||||
@@ -11,7 +11,7 @@ if (NOT DEFINED BARRIER_VERSION_MAJOR)
|
|||||||
if (DEFINED ENV{BARRIER_VERSION_MAJOR})
|
if (DEFINED ENV{BARRIER_VERSION_MAJOR})
|
||||||
set (BARRIER_VERSION_MAJOR $ENV{BARRIER_VERSION_MAJOR})
|
set (BARRIER_VERSION_MAJOR $ENV{BARRIER_VERSION_MAJOR})
|
||||||
else()
|
else()
|
||||||
set (BARRIER_VERSION_MAJOR 1)
|
set (BARRIER_VERSION_MAJOR 2)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ if (NOT DEFINED BARRIER_VERSION_MINOR)
|
|||||||
if (DEFINED ENV{BARRIER_VERSION_MINOR})
|
if (DEFINED ENV{BARRIER_VERSION_MINOR})
|
||||||
set (BARRIER_VERSION_MINOR $ENV{BARRIER_VERSION_MINOR})
|
set (BARRIER_VERSION_MINOR $ENV{BARRIER_VERSION_MINOR})
|
||||||
else()
|
else()
|
||||||
set (BARRIER_VERSION_MINOR 9)
|
set (BARRIER_VERSION_MINOR 3)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ if (NOT DEFINED BARRIER_VERSION_PATCH)
|
|||||||
if (DEFINED ENV{BARRIER_VERSION_PATCH})
|
if (DEFINED ENV{BARRIER_VERSION_PATCH})
|
||||||
set (BARRIER_VERSION_PATCH $ENV{BARRIER_VERSION_PATCH})
|
set (BARRIER_VERSION_PATCH $ENV{BARRIER_VERSION_PATCH})
|
||||||
else()
|
else()
|
||||||
set (BARRIER_VERSION_PATCH 0)
|
set (BARRIER_VERSION_PATCH 2)
|
||||||
message (WARNING "Barrier version wasn't set. Set to ${BARRIER_VERSION_MAJOR}.${BARRIER_VERSION_MINOR}.${BARRIER_VERSION_PATCH}")
|
message (WARNING "Barrier version wasn't set. Set to ${BARRIER_VERSION_MAJOR}.${BARRIER_VERSION_MINOR}.${BARRIER_VERSION_PATCH}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"
|
%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: barrier-kvm # the Barrier Snappy for Linux / not tested on MAC yet
|
name: barrier
|
||||||
base: core18
|
base: core18
|
||||||
version: master
|
version: master
|
||||||
version-script: git describe --tags --long | sed "s/^v//"
|
version-script: git describe --tags --long | sed "s/^v//"
|
||||||
adopt-info: appstream-flathub
|
adopt-info: appstream-flathub
|
||||||
@@ -43,8 +43,9 @@ parts:
|
|||||||
plugin: cmake
|
plugin: cmake
|
||||||
configflags:
|
configflags:
|
||||||
- "-DCMAKE_INSTALL_PREFIX=/usr"
|
- "-DCMAKE_INSTALL_PREFIX=/usr"
|
||||||
|
- "-DCMAKE_BUILD_TYPE=Release"
|
||||||
build-packages:
|
build-packages:
|
||||||
- xorg-dev
|
- xorg-dev
|
||||||
- libcurl4-openssl-dev
|
- libcurl4-openssl-dev
|
||||||
- libavahi-compat-libdnssd-dev
|
- libavahi-compat-libdnssd-dev
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
static ArchMutex s_mutex = NULL;
|
#include <mutex>
|
||||||
|
|
||||||
|
std::mutex s_mutex;
|
||||||
|
|
||||||
//
|
//
|
||||||
// use C library non-reentrant multibyte conversion with mutex
|
// use C library non-reentrant multibyte conversion with mutex
|
||||||
@@ -32,16 +34,14 @@ static ArchMutex s_mutex = NULL;
|
|||||||
|
|
||||||
IArchString::~IArchString()
|
IArchString::~IArchString()
|
||||||
{
|
{
|
||||||
if (s_mutex != NULL) {
|
|
||||||
ARCH->closeMutex(s_mutex);
|
|
||||||
s_mutex = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
IArchString::convStringWCToMB(char* dst,
|
IArchString::convStringWCToMB(char* dst,
|
||||||
const wchar_t* src, UInt32 n, bool* errors)
|
const wchar_t* src, UInt32 n, bool* errors)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
|
||||||
ptrdiff_t len = 0;
|
ptrdiff_t len = 0;
|
||||||
|
|
||||||
bool dummyErrors;
|
bool dummyErrors;
|
||||||
@@ -49,12 +49,6 @@ IArchString::convStringWCToMB(char* dst,
|
|||||||
errors = &dummyErrors;
|
errors = &dummyErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_mutex == NULL) {
|
|
||||||
s_mutex = ARCH->newMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
ARCH->lockMutex(s_mutex);
|
|
||||||
|
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
char dummy[MB_LEN_MAX];
|
char dummy[MB_LEN_MAX];
|
||||||
for (const wchar_t* scan = src; n > 0; ++scan, --n) {
|
for (const wchar_t* scan = src; n > 0; ++scan, --n) {
|
||||||
@@ -89,7 +83,6 @@ IArchString::convStringWCToMB(char* dst,
|
|||||||
}
|
}
|
||||||
len = dst - dst0;
|
len = dst - dst0;
|
||||||
}
|
}
|
||||||
ARCH->unlockMutex(s_mutex);
|
|
||||||
|
|
||||||
return (int)len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
@@ -98,6 +91,8 @@ int
|
|||||||
IArchString::convStringMBToWC(wchar_t* dst,
|
IArchString::convStringMBToWC(wchar_t* dst,
|
||||||
const char* src, UInt32 n_param, bool* errors)
|
const char* src, UInt32 n_param, bool* errors)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
|
||||||
ptrdiff_t n = (ptrdiff_t)n_param; // fix compiler warning
|
ptrdiff_t n = (ptrdiff_t)n_param; // fix compiler warning
|
||||||
ptrdiff_t len = 0;
|
ptrdiff_t len = 0;
|
||||||
wchar_t dummy;
|
wchar_t dummy;
|
||||||
@@ -107,12 +102,6 @@ IArchString::convStringMBToWC(wchar_t* dst,
|
|||||||
errors = &dummyErrors;
|
errors = &dummyErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_mutex == NULL) {
|
|
||||||
s_mutex = ARCH->newMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
ARCH->lockMutex(s_mutex);
|
|
||||||
|
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
for (const char* scan = src; n > 0; ) {
|
for (const char* scan = src; n > 0; ) {
|
||||||
ptrdiff_t mblen = mbtowc(&dummy, scan, n);
|
ptrdiff_t mblen = mbtowc(&dummy, scan, n);
|
||||||
@@ -184,7 +173,6 @@ IArchString::convStringMBToWC(wchar_t* dst,
|
|||||||
}
|
}
|
||||||
len = dst - dst0;
|
len = dst - dst0;
|
||||||
}
|
}
|
||||||
ARCH->unlockMutex(s_mutex);
|
|
||||||
|
|
||||||
return (int)len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,9 +114,6 @@ ArchMultithreadPosix::ArchMultithreadPosix() :
|
|||||||
m_signalUserData[i] = NULL;
|
m_signalUserData[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create mutex for thread list
|
|
||||||
m_threadMutex = newMutex();
|
|
||||||
|
|
||||||
// create thread for calling (main) thread and add it to our
|
// create thread for calling (main) thread and add it to our
|
||||||
// list. no need to lock the mutex since we're the only thread.
|
// list. no need to lock the mutex since we're the only thread.
|
||||||
m_mainThread = new ArchThreadImpl;
|
m_mainThread = new ArchThreadImpl;
|
||||||
@@ -153,26 +150,22 @@ ArchMultithreadPosix::~ArchMultithreadPosix()
|
|||||||
{
|
{
|
||||||
assert(s_instance != NULL);
|
assert(s_instance != NULL);
|
||||||
|
|
||||||
closeMutex(m_threadMutex);
|
|
||||||
s_instance = NULL;
|
s_instance = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArchMultithreadPosix::setNetworkDataForCurrentThread(void* data)
|
ArchMultithreadPosix::setNetworkDataForCurrentThread(void* data)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
ArchThreadImpl* thread = find(pthread_self());
|
ArchThreadImpl* thread = find(pthread_self());
|
||||||
thread->m_networkData = data;
|
thread->m_networkData = data;
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
ArchMultithreadPosix::getNetworkDataForThread(ArchThread thread)
|
ArchMultithreadPosix::getNetworkDataForThread(ArchThread thread)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
void* data = thread->m_networkData;
|
return thread->m_networkData;
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchMultithreadPosix*
|
ArchMultithreadPosix*
|
||||||
@@ -356,7 +349,8 @@ ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
lockMutex(m_threadMutex);
|
// note that the child thread will wait until we release this mutex
|
||||||
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
|
||||||
// create thread impl for new thread
|
// create thread impl for new thread
|
||||||
ArchThreadImpl* thread = new ArchThreadImpl;
|
ArchThreadImpl* thread = new ArchThreadImpl;
|
||||||
@@ -387,18 +381,15 @@ ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
|
|||||||
refThread(thread);
|
refThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that the child thread will wait until we release this mutex
|
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchThread
|
ArchThread
|
||||||
ArchMultithreadPosix::newCurrentThread()
|
ArchMultithreadPosix::newCurrentThread()
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
|
||||||
ArchThreadImpl* thread = find(pthread_self());
|
ArchThreadImpl* thread = find(pthread_self());
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
assert(thread != NULL);
|
assert(thread != NULL);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@@ -416,10 +407,11 @@ ArchMultithreadPosix::closeThread(ArchThread thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove thread from list
|
// remove thread from list
|
||||||
lockMutex(m_threadMutex);
|
{
|
||||||
assert(findNoRef(thread->m_thread) == thread);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
erase(thread);
|
assert(findNoRef(thread->m_thread) == thread);
|
||||||
unlockMutex(m_threadMutex);
|
erase(thread);
|
||||||
|
}
|
||||||
|
|
||||||
// done with thread
|
// done with thread
|
||||||
delete thread;
|
delete thread;
|
||||||
@@ -440,12 +432,14 @@ ArchMultithreadPosix::cancelThread(ArchThread thread)
|
|||||||
|
|
||||||
// set cancel and wakeup flags if thread can be cancelled
|
// set cancel and wakeup flags if thread can be cancelled
|
||||||
bool wakeup = false;
|
bool wakeup = false;
|
||||||
lockMutex(m_threadMutex);
|
|
||||||
if (!thread->m_exited && !thread->m_cancelling) {
|
{
|
||||||
thread->m_cancel = true;
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
wakeup = true;
|
if (!thread->m_exited && !thread->m_cancelling) {
|
||||||
|
thread->m_cancel = true;
|
||||||
|
wakeup = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
|
|
||||||
// force thread to exit system calls if wakeup is true
|
// force thread to exit system calls if wakeup is true
|
||||||
if (wakeup) {
|
if (wakeup) {
|
||||||
@@ -465,9 +459,11 @@ void
|
|||||||
ArchMultithreadPosix::testCancelThread()
|
ArchMultithreadPosix::testCancelThread()
|
||||||
{
|
{
|
||||||
// find current thread
|
// find current thread
|
||||||
lockMutex(m_threadMutex);
|
ArchThreadImpl* thread = nullptr;
|
||||||
ArchThreadImpl* thread = findNoRef(pthread_self());
|
{
|
||||||
unlockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
thread = findNoRef(pthread_self());
|
||||||
|
}
|
||||||
|
|
||||||
// test cancel on thread
|
// test cancel on thread
|
||||||
testCancelThreadImpl(thread);
|
testCancelThreadImpl(thread);
|
||||||
@@ -478,22 +474,23 @@ ArchMultithreadPosix::wait(ArchThread target, double timeout)
|
|||||||
{
|
{
|
||||||
assert(target != NULL);
|
assert(target != NULL);
|
||||||
|
|
||||||
lockMutex(m_threadMutex);
|
ArchThreadImpl* self = nullptr;
|
||||||
|
|
||||||
// find current thread
|
{
|
||||||
ArchThreadImpl* self = findNoRef(pthread_self());
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
|
||||||
// ignore wait if trying to wait on ourself
|
// find current thread
|
||||||
if (target == self) {
|
self = findNoRef(pthread_self());
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
return false;
|
// ignore wait if trying to wait on ourself
|
||||||
|
if (target == self) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref the target so it can't go away while we're watching it
|
||||||
|
refThread(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ref the target so it can't go away while we're watching it
|
|
||||||
refThread(target);
|
|
||||||
|
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// do first test regardless of timeout
|
// do first test regardless of timeout
|
||||||
testCancelThreadImpl(self);
|
testCancelThreadImpl(self);
|
||||||
@@ -538,19 +535,15 @@ ArchMultithreadPosix::isSameThread(ArchThread thread1, ArchThread thread2)
|
|||||||
bool
|
bool
|
||||||
ArchMultithreadPosix::isExitedThread(ArchThread thread)
|
ArchMultithreadPosix::isExitedThread(ArchThread thread)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
bool exited = thread->m_exited;
|
return thread->m_exited;
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
return exited;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
ArchMultithreadPosix::getResultOfThread(ArchThread thread)
|
ArchMultithreadPosix::getResultOfThread(ArchThread thread)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
void* result = thread->m_result;
|
return thread->m_result;
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IArchMultithread::ThreadID
|
IArchMultithread::ThreadID
|
||||||
@@ -563,16 +556,15 @@ void
|
|||||||
ArchMultithreadPosix::setSignalHandler(
|
ArchMultithreadPosix::setSignalHandler(
|
||||||
ESignal signal, SignalFunc func, void* userData)
|
ESignal signal, SignalFunc func, void* userData)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
m_signalFunc[signal] = func;
|
m_signalFunc[signal] = func;
|
||||||
m_signalUserData[signal] = userData;
|
m_signalUserData[signal] = userData;
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArchMultithreadPosix::raiseSignal(ESignal signal)
|
ArchMultithreadPosix::raiseSignal(ESignal signal)
|
||||||
{
|
{
|
||||||
lockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
if (m_signalFunc[signal] != NULL) {
|
if (m_signalFunc[signal] != NULL) {
|
||||||
m_signalFunc[signal](signal, m_signalUserData[signal]);
|
m_signalFunc[signal](signal, m_signalUserData[signal]);
|
||||||
pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
|
pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
|
||||||
@@ -580,7 +572,6 @@ ArchMultithreadPosix::raiseSignal(ESignal signal)
|
|||||||
else if (signal == kINTERRUPT || signal == kTERMINATE) {
|
else if (signal == kINTERRUPT || signal == kTERMINATE) {
|
||||||
ARCH->cancelThread(m_mainThread);
|
ARCH->cancelThread(m_mainThread);
|
||||||
}
|
}
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -677,15 +668,15 @@ ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl* thread)
|
|||||||
{
|
{
|
||||||
assert(thread != NULL);
|
assert(thread != NULL);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
|
||||||
// update cancel state
|
// update cancel state
|
||||||
lockMutex(m_threadMutex);
|
|
||||||
bool cancel = false;
|
bool cancel = false;
|
||||||
if (thread->m_cancel && !thread->m_cancelling) {
|
if (thread->m_cancel && !thread->m_cancelling) {
|
||||||
thread->m_cancelling = true;
|
thread->m_cancelling = true;
|
||||||
thread->m_cancel = false;
|
thread->m_cancel = false;
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
unlockMutex(m_threadMutex);
|
|
||||||
|
|
||||||
// unwind thread's stack if cancelling
|
// unwind thread's stack if cancelling
|
||||||
if (cancel) {
|
if (cancel) {
|
||||||
@@ -717,8 +708,9 @@ ArchMultithreadPosix::doThreadFunc(ArchThread thread)
|
|||||||
setPriorityOfThread(thread, 1);
|
setPriorityOfThread(thread, 1);
|
||||||
|
|
||||||
// wait for parent to initialize this object
|
// wait for parent to initialize this object
|
||||||
lockMutex(m_threadMutex);
|
{
|
||||||
unlockMutex(m_threadMutex);
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
|
}
|
||||||
|
|
||||||
void* result = NULL;
|
void* result = NULL;
|
||||||
try {
|
try {
|
||||||
@@ -731,18 +723,20 @@ ArchMultithreadPosix::doThreadFunc(ArchThread thread)
|
|||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
// note -- don't catch (...) to avoid masking bugs
|
// note -- don't catch (...) to avoid masking bugs
|
||||||
lockMutex(m_threadMutex);
|
{
|
||||||
thread->m_exited = true;
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
unlockMutex(m_threadMutex);
|
thread->m_exited = true;
|
||||||
|
}
|
||||||
closeThread(thread);
|
closeThread(thread);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// thread has exited
|
// thread has exited
|
||||||
lockMutex(m_threadMutex);
|
{
|
||||||
thread->m_result = result;
|
std::lock_guard<std::mutex> lock(m_threadMutex);
|
||||||
thread->m_exited = true;
|
thread->m_result = result;
|
||||||
unlockMutex(m_threadMutex);
|
thread->m_exited = true;
|
||||||
|
}
|
||||||
|
|
||||||
// done with thread
|
// done with thread
|
||||||
closeThread(thread);
|
closeThread(thread);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "common/stdlist.h"
|
#include "common/stdlist.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#define ARCH_MULTITHREAD ArchMultithreadPosix
|
#define ARCH_MULTITHREAD ArchMultithreadPosix
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ private:
|
|||||||
|
|
||||||
bool m_newThreadCalled;
|
bool m_newThreadCalled;
|
||||||
|
|
||||||
ArchMutex m_threadMutex;
|
std::mutex m_threadMutex;
|
||||||
ArchThread m_mainThread;
|
ArchThread m_mainThread;
|
||||||
ThreadList m_threadList;
|
ThreadList m_threadList;
|
||||||
ThreadID m_nextID;
|
ThreadID m_nextID;
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ App::initApp(int argc, const char** argv)
|
|||||||
void
|
void
|
||||||
App::initIpcClient()
|
App::initIpcClient()
|
||||||
{
|
{
|
||||||
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer);
|
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer.get());
|
||||||
m_ipcClient->connect();
|
m_ipcClient->connect();
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
|
|||||||
@@ -23,7 +23,9 @@
|
|||||||
#include "base/String.h"
|
#include "base/String.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/EventQueue.h"
|
#include "base/EventQueue.h"
|
||||||
|
#include "net/SocketMultiplexer.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
#include "barrier/win32/AppUtilWindows.h"
|
#include "barrier/win32/AppUtilWindows.h"
|
||||||
@@ -95,8 +97,8 @@ public:
|
|||||||
|
|
||||||
virtual IEventQueue* getEvents() const { return m_events; }
|
virtual IEventQueue* getEvents() const { return m_events; }
|
||||||
|
|
||||||
void setSocketMultiplexer(SocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
void setSocketMultiplexer(std::unique_ptr<SocketMultiplexer>&& sm) { m_socketMultiplexer = std::move(sm); }
|
||||||
SocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
SocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer.get(); }
|
||||||
|
|
||||||
void setEvents(EventQueue& events) { m_events = &events; }
|
void setEvents(EventQueue& events) { m_events = &events; }
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ private:
|
|||||||
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
|
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
|
||||||
ARCH_APP_UTIL m_appUtil;
|
ARCH_APP_UTIL m_appUtil;
|
||||||
IpcClient* m_ipcClient;
|
IpcClient* m_ipcClient;
|
||||||
SocketMultiplexer* m_socketMultiplexer;
|
std::unique_ptr<SocketMultiplexer> m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MinimalApp : public App {
|
class MinimalApp : public App {
|
||||||
|
|||||||
@@ -443,8 +443,7 @@ ClientApp::mainLoop()
|
|||||||
{
|
{
|
||||||
// create socket multiplexer. this must happen after daemonization
|
// create socket multiplexer. this must happen after daemonization
|
||||||
// on unix because threads evaporate across a fork().
|
// on unix because threads evaporate across a fork().
|
||||||
SocketMultiplexer multiplexer;
|
setSocketMultiplexer(std::make_unique<SocketMultiplexer>());
|
||||||
setSocketMultiplexer(&multiplexer);
|
|
||||||
|
|
||||||
// start client, etc
|
// start client, etc
|
||||||
appUtil().startNode();
|
appUtil().startNode();
|
||||||
|
|||||||
@@ -302,8 +302,8 @@ void
|
|||||||
ServerApp::stopRetryTimer()
|
ServerApp::stopRetryTimer()
|
||||||
{
|
{
|
||||||
if (m_timer != NULL) {
|
if (m_timer != NULL) {
|
||||||
|
m_events->removeHandler(Event::kTimer, m_timer);
|
||||||
m_events->deleteTimer(m_timer);
|
m_events->deleteTimer(m_timer);
|
||||||
m_events->removeHandler(Event::kTimer, NULL);
|
|
||||||
m_timer = NULL;
|
m_timer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,8 +713,7 @@ ServerApp::mainLoop()
|
|||||||
{
|
{
|
||||||
// create socket multiplexer. this must happen after daemonization
|
// create socket multiplexer. this must happen after daemonization
|
||||||
// on unix because threads evaporate across a fork().
|
// on unix because threads evaporate across a fork().
|
||||||
SocketMultiplexer multiplexer;
|
setSocketMultiplexer(std::make_unique<SocketMultiplexer>());
|
||||||
setSocketMultiplexer(&multiplexer);
|
|
||||||
|
|
||||||
// if configuration has no screens then add this system
|
// if configuration has no screens then add this system
|
||||||
// as the default
|
// as the default
|
||||||
|
|||||||
@@ -32,10 +32,13 @@ static const ButtonID kButtonNone = 0;
|
|||||||
static const ButtonID kButtonLeft = 1;
|
static const ButtonID kButtonLeft = 1;
|
||||||
static const ButtonID kButtonMiddle = 2;
|
static const ButtonID kButtonMiddle = 2;
|
||||||
static const ButtonID kButtonRight = 3;
|
static const ButtonID kButtonRight = 3;
|
||||||
|
// mouse button 4
|
||||||
static const ButtonID kButtonExtra0 = 4;
|
static const ButtonID kButtonExtra0 = 4;
|
||||||
|
// mouse button 5
|
||||||
|
static const ButtonID kButtonExtra1 = 5;
|
||||||
|
|
||||||
static const ButtonID kMacButtonRight = 2;
|
static const ButtonID kMacButtonRight = 2;
|
||||||
static const ButtonID kMacButtonMiddle = 3;
|
static const ButtonID kMacButtonMiddle = 3;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
static const UInt8 NumButtonIDs = 5;
|
static const UInt8 NumButtonIDs = 6;
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ EventQueue::EventQueue() :
|
|||||||
m_readyMutex(new Mutex),
|
m_readyMutex(new Mutex),
|
||||||
m_readyCondVar(new CondVar<bool>(m_readyMutex, false))
|
m_readyCondVar(new CondVar<bool>(m_readyMutex, false))
|
||||||
{
|
{
|
||||||
m_mutex = ARCH->newMutex();
|
|
||||||
ARCH->setSignalHandler(Arch::kINTERRUPT, &interrupt, this);
|
ARCH->setSignalHandler(Arch::kINTERRUPT, &interrupt, this);
|
||||||
ARCH->setSignalHandler(Arch::kTERMINATE, &interrupt, this);
|
ARCH->setSignalHandler(Arch::kTERMINATE, &interrupt, this);
|
||||||
m_buffer = new SimpleEventQueueBuffer;
|
m_buffer = new SimpleEventQueueBuffer;
|
||||||
@@ -104,7 +103,6 @@ EventQueue::~EventQueue()
|
|||||||
|
|
||||||
ARCH->setSignalHandler(Arch::kINTERRUPT, NULL, NULL);
|
ARCH->setSignalHandler(Arch::kINTERRUPT, NULL, NULL);
|
||||||
ARCH->setSignalHandler(Arch::kTERMINATE, NULL, NULL);
|
ARCH->setSignalHandler(Arch::kTERMINATE, NULL, NULL);
|
||||||
ARCH->closeMutex(m_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -136,7 +134,7 @@ EventQueue::loop()
|
|||||||
Event::Type
|
Event::Type
|
||||||
EventQueue::registerTypeOnce(Event::Type& type, const char* name)
|
EventQueue::registerTypeOnce(Event::Type& type, const char* name)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
if (type == Event::kUnknown) {
|
if (type == Event::kUnknown) {
|
||||||
m_typeMap.insert(std::make_pair(m_nextType, name));
|
m_typeMap.insert(std::make_pair(m_nextType, name));
|
||||||
m_nameMap.insert(std::make_pair(name, m_nextType));
|
m_nameMap.insert(std::make_pair(name, m_nextType));
|
||||||
@@ -176,7 +174,7 @@ EventQueue::getTypeName(Event::Type type)
|
|||||||
void
|
void
|
||||||
EventQueue::adoptBuffer(IEventQueueBuffer* buffer)
|
EventQueue::adoptBuffer(IEventQueueBuffer* buffer)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "adopting new buffer"));
|
LOG((CLOG_DEBUG "adopting new buffer"));
|
||||||
|
|
||||||
@@ -261,7 +259,7 @@ retry:
|
|||||||
|
|
||||||
case IEventQueueBuffer::kUser:
|
case IEventQueueBuffer::kUser:
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
event = removeEvent(dataID);
|
event = removeEvent(dataID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -316,7 +314,7 @@ EventQueue::addEvent(const Event& event)
|
|||||||
void
|
void
|
||||||
EventQueue::addEventToBuffer(const Event& event)
|
EventQueue::addEventToBuffer(const Event& event)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
// store the event's data locally
|
// store the event's data locally
|
||||||
UInt32 eventID = saveEvent(event);
|
UInt32 eventID = saveEvent(event);
|
||||||
@@ -338,7 +336,7 @@ EventQueue::newTimer(double duration, void* target)
|
|||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
target = timer;
|
target = timer;
|
||||||
}
|
}
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
m_timers.insert(timer);
|
m_timers.insert(timer);
|
||||||
// initial duration is requested duration plus whatever's on
|
// initial duration is requested duration plus whatever's on
|
||||||
// the clock currently because the latter will be subtracted
|
// the clock currently because the latter will be subtracted
|
||||||
@@ -357,7 +355,7 @@ EventQueue::newOneShotTimer(double duration, void* target)
|
|||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
target = timer;
|
target = timer;
|
||||||
}
|
}
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
m_timers.insert(timer);
|
m_timers.insert(timer);
|
||||||
// initial duration is requested duration plus whatever's on
|
// initial duration is requested duration plus whatever's on
|
||||||
// the clock currently because the latter will be subtracted
|
// the clock currently because the latter will be subtracted
|
||||||
@@ -370,7 +368,7 @@ EventQueue::newOneShotTimer(double duration, void* target)
|
|||||||
void
|
void
|
||||||
EventQueue::deleteTimer(EventQueueTimer* timer)
|
EventQueue::deleteTimer(EventQueueTimer* timer)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
for (TimerQueue::iterator index = m_timerQueue.begin();
|
for (TimerQueue::iterator index = m_timerQueue.begin();
|
||||||
index != m_timerQueue.end(); ++index) {
|
index != m_timerQueue.end(); ++index) {
|
||||||
if (index->getTimer() == timer) {
|
if (index->getTimer() == timer) {
|
||||||
@@ -388,7 +386,7 @@ EventQueue::deleteTimer(EventQueueTimer* timer)
|
|||||||
void
|
void
|
||||||
EventQueue::adoptHandler(Event::Type type, void* target, IEventJob* handler)
|
EventQueue::adoptHandler(Event::Type type, void* target, IEventJob* handler)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
IEventJob*& job = m_handlers[target][type];
|
IEventJob*& job = m_handlers[target][type];
|
||||||
delete job;
|
delete job;
|
||||||
job = handler;
|
job = handler;
|
||||||
@@ -399,7 +397,7 @@ EventQueue::removeHandler(Event::Type type, void* target)
|
|||||||
{
|
{
|
||||||
IEventJob* handler = NULL;
|
IEventJob* handler = NULL;
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
HandlerTable::iterator index = m_handlers.find(target);
|
HandlerTable::iterator index = m_handlers.find(target);
|
||||||
if (index != m_handlers.end()) {
|
if (index != m_handlers.end()) {
|
||||||
TypeHandlerTable& typeHandlers = index->second;
|
TypeHandlerTable& typeHandlers = index->second;
|
||||||
@@ -418,7 +416,7 @@ EventQueue::removeHandlers(void* target)
|
|||||||
{
|
{
|
||||||
std::vector<IEventJob*> handlers;
|
std::vector<IEventJob*> handlers;
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
HandlerTable::iterator index = m_handlers.find(target);
|
HandlerTable::iterator index = m_handlers.find(target);
|
||||||
if (index != m_handlers.end()) {
|
if (index != m_handlers.end()) {
|
||||||
// copy to handlers array and clear table for target
|
// copy to handlers array and clear table for target
|
||||||
@@ -447,7 +445,7 @@ EventQueue::isEmpty() const
|
|||||||
IEventJob*
|
IEventJob*
|
||||||
EventQueue::getHandler(Event::Type type, void* target) const
|
EventQueue::getHandler(Event::Type type, void* target) const
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
HandlerTable::const_iterator index = m_handlers.find(target);
|
HandlerTable::const_iterator index = m_handlers.find(target);
|
||||||
if (index != m_handlers.end()) {
|
if (index != m_handlers.end()) {
|
||||||
const TypeHandlerTable& typeHandlers = index->second;
|
const TypeHandlerTable& typeHandlers = index->second;
|
||||||
|
|||||||
@@ -28,10 +28,9 @@
|
|||||||
#include "common/stdset.h"
|
#include "common/stdset.h"
|
||||||
#include "base/NonBlockingStream.h"
|
#include "base/NonBlockingStream.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
class Mutex;
|
|
||||||
|
|
||||||
//! Event queue
|
//! Event queue
|
||||||
/*!
|
/*!
|
||||||
An event queue that implements the platform independent parts and
|
An event queue that implements the platform independent parts and
|
||||||
@@ -114,7 +113,7 @@ private:
|
|||||||
typedef std::map<void*, TypeHandlerTable> HandlerTable;
|
typedef std::map<void*, TypeHandlerTable> HandlerTable;
|
||||||
|
|
||||||
int m_systemTarget;
|
int m_systemTarget;
|
||||||
ArchMutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
|
|
||||||
// registered events
|
// registered events
|
||||||
Event::Type m_nextType;
|
Event::Type m_nextType;
|
||||||
|
|||||||
@@ -63,9 +63,6 @@ Log::Log()
|
|||||||
{
|
{
|
||||||
assert(s_log == NULL);
|
assert(s_log == NULL);
|
||||||
|
|
||||||
// create mutex for multithread safe operation
|
|
||||||
m_mutex = ARCH->newMutex();
|
|
||||||
|
|
||||||
// other initalization
|
// other initalization
|
||||||
m_maxPriority = g_defaultMaxPriority;
|
m_maxPriority = g_defaultMaxPriority;
|
||||||
m_maxNewlineLength = 0;
|
m_maxNewlineLength = 0;
|
||||||
@@ -90,7 +87,6 @@ Log::~Log()
|
|||||||
index != m_alwaysOutputters.end(); ++index) {
|
index != m_alwaysOutputters.end(); ++index) {
|
||||||
delete *index;
|
delete *index;
|
||||||
}
|
}
|
||||||
ARCH->closeMutex(m_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log*
|
Log*
|
||||||
@@ -214,7 +210,7 @@ Log::insert(ILogOutputter* outputter, bool alwaysAtHead)
|
|||||||
{
|
{
|
||||||
assert(outputter != NULL);
|
assert(outputter != NULL);
|
||||||
|
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
if (alwaysAtHead) {
|
if (alwaysAtHead) {
|
||||||
m_alwaysOutputters.push_front(outputter);
|
m_alwaysOutputters.push_front(outputter);
|
||||||
}
|
}
|
||||||
@@ -237,7 +233,7 @@ Log::insert(ILogOutputter* outputter, bool alwaysAtHead)
|
|||||||
void
|
void
|
||||||
Log::remove(ILogOutputter* outputter)
|
Log::remove(ILogOutputter* outputter)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
m_outputters.remove(outputter);
|
m_outputters.remove(outputter);
|
||||||
m_alwaysOutputters.remove(outputter);
|
m_alwaysOutputters.remove(outputter);
|
||||||
}
|
}
|
||||||
@@ -245,7 +241,7 @@ Log::remove(ILogOutputter* outputter)
|
|||||||
void
|
void
|
||||||
Log::pop_front(bool alwaysAtHead)
|
Log::pop_front(bool alwaysAtHead)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
OutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
|
OutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
|
||||||
if (!list->empty()) {
|
if (!list->empty()) {
|
||||||
delete list->front();
|
delete list->front();
|
||||||
@@ -271,14 +267,14 @@ Log::setFilter(const char* maxPriority)
|
|||||||
void
|
void
|
||||||
Log::setFilter(int maxPriority)
|
Log::setFilter(int maxPriority)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
m_maxPriority = maxPriority;
|
m_maxPriority = maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Log::getFilter() const
|
Log::getFilter() const
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
return m_maxPriority;
|
return m_maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +285,7 @@ Log::output(ELevel priority, char* msg)
|
|||||||
assert(msg != NULL);
|
assert(msg != NULL);
|
||||||
if (!msg) return;
|
if (!msg) return;
|
||||||
|
|
||||||
ArchMutexLock lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
OutputterList::const_iterator i;
|
OutputterList::const_iterator i;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "common/stdlist.h"
|
#include "common/stdlist.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#define CLOG (Log::getInstance())
|
#define CLOG (Log::getInstance())
|
||||||
#define BYE "\nTry `%s --help' for more information."
|
#define BYE "\nTry `%s --help' for more information."
|
||||||
@@ -132,7 +133,7 @@ private:
|
|||||||
|
|
||||||
static Log* s_log;
|
static Log* s_log;
|
||||||
|
|
||||||
ArchMutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
OutputterList m_outputters;
|
OutputterList m_outputters;
|
||||||
OutputterList m_alwaysOutputters;
|
OutputterList m_alwaysOutputters;
|
||||||
int m_maxNewlineLength;
|
int m_maxNewlineLength;
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ IpcClientProxy::IpcClientProxy(barrier::IStream& stream, IEventQueue* events) :
|
|||||||
m_stream(stream),
|
m_stream(stream),
|
||||||
m_clientType(kIpcClientUnknown),
|
m_clientType(kIpcClientUnknown),
|
||||||
m_disconnecting(false),
|
m_disconnecting(false),
|
||||||
m_readMutex(ARCH->newMutex()),
|
|
||||||
m_writeMutex(ARCH->newMutex()),
|
|
||||||
m_events(events)
|
m_events(events)
|
||||||
{
|
{
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
@@ -71,14 +69,11 @@ IpcClientProxy::~IpcClientProxy()
|
|||||||
m_events->forIStream().outputShutdown(), m_stream.getEventTarget());
|
m_events->forIStream().outputShutdown(), m_stream.getEventTarget());
|
||||||
|
|
||||||
// don't delete the stream while it's being used.
|
// don't delete the stream while it's being used.
|
||||||
ARCH->lockMutex(m_readMutex);
|
{
|
||||||
ARCH->lockMutex(m_writeMutex);
|
std::lock_guard<std::mutex> lock_read(m_readMutex);
|
||||||
delete &m_stream;
|
std::lock_guard<std::mutex> lock_write(m_writeMutex);
|
||||||
ARCH->unlockMutex(m_readMutex);
|
delete &m_stream;
|
||||||
ARCH->unlockMutex(m_writeMutex);
|
}
|
||||||
|
|
||||||
ARCH->closeMutex(m_readMutex);
|
|
||||||
ARCH->closeMutex(m_writeMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -99,7 +94,7 @@ void
|
|||||||
IpcClientProxy::handleData(const Event&, void*)
|
IpcClientProxy::handleData(const Event&, void*)
|
||||||
{
|
{
|
||||||
// don't allow the dtor to destroy the stream while we're using it.
|
// don't allow the dtor to destroy the stream while we're using it.
|
||||||
ArchMutexLock lock(m_readMutex);
|
std::lock_guard<std::mutex> lock(m_readMutex);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "start ipc handle data"));
|
LOG((CLOG_DEBUG "start ipc handle data"));
|
||||||
|
|
||||||
@@ -139,7 +134,7 @@ IpcClientProxy::send(const IpcMessage& message)
|
|||||||
// don't allow other threads to write until we've finished the entire
|
// don't allow other threads to write until we've finished the entire
|
||||||
// message. stream write is locked, but only for that single write.
|
// message. stream write is locked, but only for that single write.
|
||||||
// also, don't allow the dtor to destroy the stream while we're using it.
|
// also, don't allow the dtor to destroy the stream while we're using it.
|
||||||
ArchMutexLock lock(m_writeMutex);
|
std::lock_guard<std::mutex> lock(m_writeMutex);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
|
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace barrier { class IStream; }
|
namespace barrier { class IStream; }
|
||||||
class IpcMessage;
|
class IpcMessage;
|
||||||
class IpcCommandMessage;
|
class IpcCommandMessage;
|
||||||
@@ -49,7 +51,7 @@ private:
|
|||||||
barrier::IStream& m_stream;
|
barrier::IStream& m_stream;
|
||||||
EIpcClientType m_clientType;
|
EIpcClientType m_clientType;
|
||||||
bool m_disconnecting;
|
bool m_disconnecting;
|
||||||
ArchMutex m_readMutex;
|
std::mutex m_readMutex;
|
||||||
ArchMutex m_writeMutex;
|
std::mutex m_writeMutex;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ enum EIpcLogOutputter {
|
|||||||
|
|
||||||
IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread) :
|
IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread) :
|
||||||
m_ipcServer(ipcServer),
|
m_ipcServer(ipcServer),
|
||||||
m_bufferMutex(ARCH->newMutex()),
|
|
||||||
m_sending(false),
|
m_sending(false),
|
||||||
m_bufferThread(nullptr),
|
m_bufferThread(nullptr),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
@@ -52,8 +51,7 @@ IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType
|
|||||||
m_bufferRateTimeLimit(kBufferRateTimeLimit),
|
m_bufferRateTimeLimit(kBufferRateTimeLimit),
|
||||||
m_bufferWriteCount(0),
|
m_bufferWriteCount(0),
|
||||||
m_bufferRateStart(ARCH->time()),
|
m_bufferRateStart(ARCH->time()),
|
||||||
m_clientType(clientType),
|
m_clientType(clientType)
|
||||||
m_runningMutex(ARCH->newMutex())
|
|
||||||
{
|
{
|
||||||
if (useThread) {
|
if (useThread) {
|
||||||
m_bufferThread = new Thread(new TMethodJob<IpcLogOutputter>(
|
m_bufferThread = new Thread(new TMethodJob<IpcLogOutputter>(
|
||||||
@@ -65,8 +63,6 @@ IpcLogOutputter::~IpcLogOutputter()
|
|||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
ARCH->closeMutex(m_bufferMutex);
|
|
||||||
|
|
||||||
if (m_bufferThread != nullptr) {
|
if (m_bufferThread != nullptr) {
|
||||||
m_bufferThread->cancel();
|
m_bufferThread->cancel();
|
||||||
m_bufferThread->wait();
|
m_bufferThread->wait();
|
||||||
@@ -86,7 +82,7 @@ void
|
|||||||
IpcLogOutputter::close()
|
IpcLogOutputter::close()
|
||||||
{
|
{
|
||||||
if (m_bufferThread != nullptr) {
|
if (m_bufferThread != nullptr) {
|
||||||
ArchMutexLock lock(m_runningMutex);
|
std::lock_guard<std::mutex> lock(m_runningMutex);
|
||||||
m_running = false;
|
m_running = false;
|
||||||
notifyBuffer();
|
notifyBuffer();
|
||||||
m_bufferThread->wait(5);
|
m_bufferThread->wait(5);
|
||||||
@@ -116,7 +112,7 @@ IpcLogOutputter::write(ELevel, const char* text)
|
|||||||
void
|
void
|
||||||
IpcLogOutputter::appendBuffer(const String& text)
|
IpcLogOutputter::appendBuffer(const String& text)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_bufferMutex);
|
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||||
|
|
||||||
double elapsed = ARCH->time() - m_bufferRateStart;
|
double elapsed = ARCH->time() - m_bufferRateStart;
|
||||||
if (elapsed < m_bufferRateTimeLimit) {
|
if (elapsed < m_bufferRateTimeLimit) {
|
||||||
@@ -143,7 +139,7 @@ IpcLogOutputter::appendBuffer(const String& text)
|
|||||||
bool
|
bool
|
||||||
IpcLogOutputter::isRunning()
|
IpcLogOutputter::isRunning()
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_runningMutex);
|
std::lock_guard<std::mutex> lock(m_runningMutex);
|
||||||
return m_running;
|
return m_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +176,7 @@ IpcLogOutputter::notifyBuffer()
|
|||||||
String
|
String
|
||||||
IpcLogOutputter::getChunk(size_t count)
|
IpcLogOutputter::getChunk(size_t count)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_bufferMutex);
|
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||||
|
|
||||||
if (m_buffer.size() < count) {
|
if (m_buffer.size() < count) {
|
||||||
count = m_buffer.size();
|
count = m_buffer.size();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "ipc/Ipc.h"
|
#include "ipc/Ipc.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class IpcServer;
|
class IpcServer;
|
||||||
class Event;
|
class Event;
|
||||||
@@ -100,7 +101,7 @@ private:
|
|||||||
|
|
||||||
IpcServer& m_ipcServer;
|
IpcServer& m_ipcServer;
|
||||||
Buffer m_buffer;
|
Buffer m_buffer;
|
||||||
ArchMutex m_bufferMutex;
|
std::mutex m_bufferMutex;
|
||||||
bool m_sending;
|
bool m_sending;
|
||||||
Thread* m_bufferThread;
|
Thread* m_bufferThread;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
@@ -115,5 +116,5 @@ private:
|
|||||||
UInt16 m_bufferWriteCount;
|
UInt16 m_bufferWriteCount;
|
||||||
double m_bufferRateStart;
|
double m_bufferRateStart;
|
||||||
EIpcClientType m_clientType;
|
EIpcClientType m_clientType;
|
||||||
ArchMutex m_runningMutex;
|
std::mutex m_runningMutex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ IpcServer::init()
|
|||||||
{
|
{
|
||||||
m_socket = new TCPListenSocket(m_events, m_socketMultiplexer, IArchNetwork::kINET);
|
m_socket = new TCPListenSocket(m_events, m_socketMultiplexer, IArchNetwork::kINET);
|
||||||
|
|
||||||
m_clientsMutex = ARCH->newMutex();
|
|
||||||
m_address.resolve();
|
m_address.resolve();
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
@@ -75,15 +74,15 @@ IpcServer::~IpcServer()
|
|||||||
delete m_socket;
|
delete m_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARCH->lockMutex(m_clientsMutex);
|
{
|
||||||
ClientList::iterator it;
|
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
ClientList::iterator it;
|
||||||
deleteClient(*it);
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||||
|
deleteClient(*it);
|
||||||
|
}
|
||||||
|
m_clients.clear();
|
||||||
}
|
}
|
||||||
m_clients.clear();
|
|
||||||
ARCH->unlockMutex(m_clientsMutex);
|
|
||||||
ARCH->closeMutex(m_clientsMutex);
|
|
||||||
|
|
||||||
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_socket);
|
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +102,12 @@ IpcServer::handleClientConnecting(const Event&, void*)
|
|||||||
|
|
||||||
LOG((CLOG_DEBUG "accepted ipc client connection"));
|
LOG((CLOG_DEBUG "accepted ipc client connection"));
|
||||||
|
|
||||||
ARCH->lockMutex(m_clientsMutex);
|
IpcClientProxy* proxy = nullptr;
|
||||||
IpcClientProxy* proxy = new IpcClientProxy(*stream, m_events);
|
{
|
||||||
m_clients.push_back(proxy);
|
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||||
ARCH->unlockMutex(m_clientsMutex);
|
proxy = new IpcClientProxy(*stream, m_events);
|
||||||
|
m_clients.push_back(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
m_events->forIpcClientProxy().disconnected(), proxy,
|
m_events->forIpcClientProxy().disconnected(), proxy,
|
||||||
@@ -127,7 +128,7 @@ IpcServer::handleClientDisconnected(const Event& e, void*)
|
|||||||
{
|
{
|
||||||
IpcClientProxy* proxy = static_cast<IpcClientProxy*>(e.getTarget());
|
IpcClientProxy* proxy = static_cast<IpcClientProxy*>(e.getTarget());
|
||||||
|
|
||||||
ArchMutexLock lock(m_clientsMutex);
|
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||||
m_clients.remove(proxy);
|
m_clients.remove(proxy);
|
||||||
deleteClient(proxy);
|
deleteClient(proxy);
|
||||||
|
|
||||||
@@ -153,7 +154,7 @@ IpcServer::deleteClient(IpcClientProxy* proxy)
|
|||||||
bool
|
bool
|
||||||
IpcServer::hasClients(EIpcClientType clientType) const
|
IpcServer::hasClients(EIpcClientType clientType) const
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_clientsMutex);
|
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||||
|
|
||||||
if (m_clients.empty()) {
|
if (m_clients.empty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -175,7 +176,7 @@ IpcServer::hasClients(EIpcClientType clientType) const
|
|||||||
void
|
void
|
||||||
IpcServer::send(const IpcMessage& message, EIpcClientType filterType)
|
IpcServer::send(const IpcMessage& message, EIpcClientType filterType)
|
||||||
{
|
{
|
||||||
ArchMutexLock lock(m_clientsMutex);
|
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||||
|
|
||||||
ClientList::iterator it;
|
ClientList::iterator it;
|
||||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class Event;
|
class Event;
|
||||||
class IpcClientProxy;
|
class IpcClientProxy;
|
||||||
@@ -79,7 +80,7 @@ private:
|
|||||||
TCPListenSocket* m_socket;
|
TCPListenSocket* m_socket;
|
||||||
NetworkAddress m_address;
|
NetworkAddress m_address;
|
||||||
ClientList m_clients;
|
ClientList m_clients;
|
||||||
ArchMutex m_clientsMutex;
|
mutable std::mutex m_clientsMutex;
|
||||||
|
|
||||||
#ifdef TEST_ENV
|
#ifdef TEST_ENV
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -20,6 +20,19 @@
|
|||||||
|
|
||||||
#include "arch/IArchNetwork.h"
|
#include "arch/IArchNetwork.h"
|
||||||
#include "common/IInterface.h"
|
#include "common/IInterface.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class ISocketMultiplexerJob;
|
||||||
|
|
||||||
|
struct MultiplexerJobStatus
|
||||||
|
{
|
||||||
|
MultiplexerJobStatus(bool cont, std::unique_ptr<ISocketMultiplexerJob>&& nj) :
|
||||||
|
continue_servicing(cont), new_job(std::move(nj))
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool continue_servicing = false;
|
||||||
|
std::unique_ptr<ISocketMultiplexerJob> new_job;
|
||||||
|
};
|
||||||
|
|
||||||
//! Socket multiplexer job
|
//! Socket multiplexer job
|
||||||
/*!
|
/*!
|
||||||
@@ -32,21 +45,20 @@ public:
|
|||||||
|
|
||||||
//! Handle socket event
|
//! Handle socket event
|
||||||
/*!
|
/*!
|
||||||
Called by a socket multiplexer when the socket becomes readable,
|
Called by a socket multiplexer when the socket becomes readable, writable, or has an error.
|
||||||
writable, or has an error. It should return itself if the same
|
The socket is readable if \p readable is true, writable if \p writable is true, and in error
|
||||||
job can continue to service events, a new job if the socket must
|
if \p error is true.
|
||||||
be serviced differently, or NULL if the socket should no longer
|
|
||||||
be serviced. The socket is readable if \p readable is true,
|
The method returns false as the continue_servicing member of the returned struct if the socket
|
||||||
writable if \p writable is true, and in error if \p error is
|
should no longer be served and true otherwise. Additionally, if the new_job member of the
|
||||||
true.
|
returned pair is not empty, the socket should be serviced differently with the specified job.
|
||||||
|
|
||||||
This call must not attempt to directly change the job for this
|
This call must not attempt to directly change the job for this
|
||||||
socket by calling \c addSocket() or \c removeSocket() on the
|
socket by calling \c addSocket() or \c removeSocket() on the
|
||||||
multiplexer. It must instead return the new job. It can,
|
multiplexer. It must instead return the new job. It can,
|
||||||
however, add or remove jobs for other sockets.
|
however, add or remove jobs for other sockets.
|
||||||
*/
|
*/
|
||||||
virtual ISocketMultiplexerJob*
|
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) = 0;
|
||||||
run(bool readable, bool writable, bool error) = 0;
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
@@ -72,5 +84,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool isWritable() const = 0;
|
virtual bool isWritable() const = 0;
|
||||||
|
|
||||||
|
virtual bool isCursor() const { return false; }
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,17 +83,9 @@ SecureSocket::~SecureSocket()
|
|||||||
// take socket from multiplexer ASAP otherwise the race condition
|
// take socket from multiplexer ASAP otherwise the race condition
|
||||||
// could cause events to get called on a dead object. TCPSocket
|
// could cause events to get called on a dead object. TCPSocket
|
||||||
// will do this, too, but the double-call is harmless
|
// will do this, too, but the double-call is harmless
|
||||||
setJob(NULL);
|
removeJob();
|
||||||
if (m_ssl->m_ssl != NULL) {
|
freeSSLResources();
|
||||||
SSL_shutdown(m_ssl->m_ssl);
|
|
||||||
|
|
||||||
SSL_free(m_ssl->m_ssl);
|
|
||||||
m_ssl->m_ssl = NULL;
|
|
||||||
}
|
|
||||||
if (m_ssl->m_context != NULL) {
|
|
||||||
SSL_CTX_free(m_ssl->m_context);
|
|
||||||
m_ssl->m_context = NULL;
|
|
||||||
}
|
|
||||||
// removing sleep() because I have no idea why you would want to do it
|
// removing sleep() because I have no idea why you would want to do it
|
||||||
// ... smells of trying to cover up a bug you don't understand
|
// ... smells of trying to cover up a bug you don't understand
|
||||||
//ARCH->sleep(1);
|
//ARCH->sleep(1);
|
||||||
@@ -104,12 +96,24 @@ void
|
|||||||
SecureSocket::close()
|
SecureSocket::close()
|
||||||
{
|
{
|
||||||
isFatal(true);
|
isFatal(true);
|
||||||
|
freeSSLResources();
|
||||||
SSL_shutdown(m_ssl->m_ssl);
|
|
||||||
|
|
||||||
TCPSocket::close();
|
TCPSocket::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SecureSocket::freeSSLResources()
|
||||||
|
{
|
||||||
|
if (m_ssl->m_ssl != NULL) {
|
||||||
|
SSL_shutdown(m_ssl->m_ssl);
|
||||||
|
SSL_free(m_ssl->m_ssl);
|
||||||
|
m_ssl->m_ssl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ssl->m_context != NULL) {
|
||||||
|
SSL_CTX_free(m_ssl->m_context);
|
||||||
|
m_ssl->m_context = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SecureSocket::connect(const NetworkAddress& addr)
|
SecureSocket::connect(const NetworkAddress& addr)
|
||||||
{
|
{
|
||||||
@@ -121,13 +125,12 @@ SecureSocket::connect(const NetworkAddress& addr)
|
|||||||
TCPSocket::connect(addr);
|
TCPSocket::connect(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
std::unique_ptr<ISocketMultiplexerJob> SecureSocket::newJob()
|
||||||
SecureSocket::newJob()
|
|
||||||
{
|
{
|
||||||
// after TCP connection is established, SecureSocket will pick up
|
// after TCP connection is established, SecureSocket will pick up
|
||||||
// connected event and do secureConnect
|
// connected event and do secureConnect
|
||||||
if (m_connected && !m_secureReady) {
|
if (m_connected && !m_secureReady) {
|
||||||
return NULL;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return TCPSocket::newJob();
|
return TCPSocket::newJob();
|
||||||
@@ -136,7 +139,7 @@ SecureSocket::newJob()
|
|||||||
void
|
void
|
||||||
SecureSocket::secureConnect()
|
SecureSocket::secureConnect()
|
||||||
{
|
{
|
||||||
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
|
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
|
||||||
this, &SecureSocket::serviceConnect,
|
this, &SecureSocket::serviceConnect,
|
||||||
getSocket(), isReadable(), isWritable()));
|
getSocket(), isReadable(), isWritable()));
|
||||||
}
|
}
|
||||||
@@ -144,7 +147,7 @@ SecureSocket::secureConnect()
|
|||||||
void
|
void
|
||||||
SecureSocket::secureAccept()
|
SecureSocket::secureAccept()
|
||||||
{
|
{
|
||||||
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
|
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
|
||||||
this, &SecureSocket::serviceAccept,
|
this, &SecureSocket::serviceAccept,
|
||||||
getSocket(), isReadable(), isWritable()));
|
getSocket(), isReadable(), isWritable()));
|
||||||
}
|
}
|
||||||
@@ -736,10 +739,11 @@ SecureSocket::verifyCertFingerprint()
|
|||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
|
||||||
SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
|
bool read, bool write, bool error)
|
||||||
bool, bool write, bool error)
|
|
||||||
{
|
{
|
||||||
|
(void) read;
|
||||||
|
|
||||||
Lock lock(&getMutex());
|
Lock lock(&getMutex());
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@@ -751,25 +755,28 @@ SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
|
|||||||
|
|
||||||
// If status < 0, error happened
|
// If status < 0, error happened
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
return NULL;
|
return {false, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If status > 0, success
|
// If status > 0, success
|
||||||
if (status > 0) {
|
if (status > 0) {
|
||||||
sendEvent(m_events->forIDataSocket().secureConnected());
|
sendEvent(m_events->forIDataSocket().secureConnected());
|
||||||
return newJob();
|
return {true, newJob()};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry case
|
// Retry case
|
||||||
return new TSocketMultiplexerMethodJob<SecureSocket>(
|
return {
|
||||||
|
true,
|
||||||
|
std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
|
||||||
this, &SecureSocket::serviceConnect,
|
this, &SecureSocket::serviceConnect,
|
||||||
getSocket(), isReadable(), isWritable());
|
getSocket(), isReadable(), isWritable())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
|
||||||
SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
|
bool read, bool write, bool error)
|
||||||
bool, bool write, bool error)
|
|
||||||
{
|
{
|
||||||
|
(void) read;
|
||||||
Lock lock(&getMutex());
|
Lock lock(&getMutex());
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@@ -780,19 +787,19 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
|
|||||||
#endif
|
#endif
|
||||||
// If status < 0, error happened
|
// If status < 0, error happened
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
return NULL;
|
return {false, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If status > 0, success
|
// If status > 0, success
|
||||||
if (status > 0) {
|
if (status > 0) {
|
||||||
sendEvent(m_events->forClientListener().accepted());
|
sendEvent(m_events->forClientListener().accepted());
|
||||||
return newJob();
|
return {true, newJob()};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry case
|
// Retry case
|
||||||
return new TSocketMultiplexerMethodJob<SecureSocket>(
|
return {true, std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
|
||||||
this, &SecureSocket::serviceAccept,
|
this, &SecureSocket::serviceAccept,
|
||||||
getSocket(), isReadable(), isWritable());
|
getSocket(), isReadable(), isWritable())};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ public:
|
|||||||
// IDataSocket overrides
|
// IDataSocket overrides
|
||||||
virtual void connect(const NetworkAddress&);
|
virtual void connect(const NetworkAddress&);
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
std::unique_ptr<ISocketMultiplexerJob> newJob() override;
|
||||||
newJob();
|
|
||||||
bool isFatal() const { return m_fatal; }
|
bool isFatal() const { return m_fatal; }
|
||||||
void isFatal(bool b) { m_fatal = b; }
|
void isFatal(bool b) { m_fatal = b; }
|
||||||
bool isSecureReady();
|
bool isSecureReady();
|
||||||
@@ -74,13 +73,8 @@ private:
|
|||||||
bool separator = true);
|
bool separator = true);
|
||||||
bool verifyCertFingerprint();
|
bool verifyCertFingerprint();
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus serviceConnect(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
serviceConnect(ISocketMultiplexerJob*,
|
MultiplexerJobStatus serviceAccept(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
bool, bool, bool);
|
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
|
||||||
serviceAccept(ISocketMultiplexerJob*,
|
|
||||||
bool, bool, bool);
|
|
||||||
|
|
||||||
void showSecureConnectInfo();
|
void showSecureConnectInfo();
|
||||||
void showSecureLibInfo();
|
void showSecureLibInfo();
|
||||||
@@ -88,6 +82,8 @@ private:
|
|||||||
|
|
||||||
void handleTCPConnected(const Event& event, void*);
|
void handleTCPConnected(const Event& event, void*);
|
||||||
|
|
||||||
|
void freeSSLResources();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ssl* m_ssl;
|
Ssl* m_ssl;
|
||||||
bool m_secureReady;
|
bool m_secureReady;
|
||||||
|
|||||||
@@ -33,6 +33,20 @@
|
|||||||
// SocketMultiplexer
|
// SocketMultiplexer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
class CursorMultiplexerJob : public ISocketMultiplexerJob {
|
||||||
|
public:
|
||||||
|
MultiplexerJobStatus run(bool readable, bool writable, bool error) override
|
||||||
|
{
|
||||||
|
return {false, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
ArchSocket getSocket() const override { return {}; }
|
||||||
|
bool isReadable() const override { return false; }
|
||||||
|
bool isWritable() const override { return false; }
|
||||||
|
bool isCursor() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
SocketMultiplexer::SocketMultiplexer() :
|
SocketMultiplexer::SocketMultiplexer() :
|
||||||
m_mutex(new Mutex),
|
m_mutex(new Mutex),
|
||||||
m_thread(NULL),
|
m_thread(NULL),
|
||||||
@@ -43,12 +57,6 @@ SocketMultiplexer::SocketMultiplexer() :
|
|||||||
m_jobListLocker(NULL),
|
m_jobListLocker(NULL),
|
||||||
m_jobListLockLocker(NULL)
|
m_jobListLockLocker(NULL)
|
||||||
{
|
{
|
||||||
// this pointer just has to be unique and not NULL. it will
|
|
||||||
// never be dereferenced. it's used to identify cursor nodes
|
|
||||||
// in the jobs list.
|
|
||||||
// TODO: Remove this evilness
|
|
||||||
m_cursorMark = reinterpret_cast<ISocketMultiplexerJob*>(this);
|
|
||||||
|
|
||||||
// start thread
|
// start thread
|
||||||
m_thread = new Thread(new TMethodJob<SocketMultiplexer>(
|
m_thread = new Thread(new TMethodJob<SocketMultiplexer>(
|
||||||
this, &SocketMultiplexer::serviceThread));
|
this, &SocketMultiplexer::serviceThread));
|
||||||
@@ -66,16 +74,9 @@ SocketMultiplexer::~SocketMultiplexer()
|
|||||||
delete m_jobListLocker;
|
delete m_jobListLocker;
|
||||||
delete m_jobListLockLocker;
|
delete m_jobListLockLocker;
|
||||||
delete m_mutex;
|
delete m_mutex;
|
||||||
|
|
||||||
// clean up jobs
|
|
||||||
for (SocketJobMap::iterator i = m_socketJobMap.begin();
|
|
||||||
i != m_socketJobMap.end(); ++i) {
|
|
||||||
delete *(i->second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SocketMultiplexer::addSocket(ISocket* socket, std::unique_ptr<ISocketMultiplexerJob>&& job)
|
||||||
SocketMultiplexer::addSocket(ISocket* socket, ISocketMultiplexerJob* job)
|
|
||||||
{
|
{
|
||||||
assert(socket != NULL);
|
assert(socket != NULL);
|
||||||
assert(job != NULL);
|
assert(job != NULL);
|
||||||
@@ -95,16 +96,12 @@ SocketMultiplexer::addSocket(ISocket* socket, ISocketMultiplexerJob* job)
|
|||||||
// we *must* put the job at the end so the order of jobs in
|
// we *must* put the job at the end so the order of jobs in
|
||||||
// the list continue to match the order of jobs in pfds in
|
// the list continue to match the order of jobs in pfds in
|
||||||
// serviceThread().
|
// serviceThread().
|
||||||
JobCursor j = m_socketJobs.insert(m_socketJobs.end(), job);
|
JobCursor j = m_socketJobs.insert(m_socketJobs.end(), std::move(job));
|
||||||
m_update = true;
|
m_update = true;
|
||||||
m_socketJobMap.insert(std::make_pair(socket, j));
|
m_socketJobMap.insert(std::make_pair(socket, j));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JobCursor j = i->second;
|
*(i->second) = std::move(job);
|
||||||
if (*j != job) {
|
|
||||||
delete *j;
|
|
||||||
*j = job;
|
|
||||||
}
|
|
||||||
m_update = true;
|
m_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,10 +128,9 @@ SocketMultiplexer::removeSocket(ISocket* socket)
|
|||||||
// to match the order of jobs in pfds in serviceThread().
|
// to match the order of jobs in pfds in serviceThread().
|
||||||
SocketJobMap::iterator i = m_socketJobMap.find(socket);
|
SocketJobMap::iterator i = m_socketJobMap.find(socket);
|
||||||
if (i != m_socketJobMap.end()) {
|
if (i != m_socketJobMap.end()) {
|
||||||
if (*(i->second) != NULL) {
|
if (*(i->second)) {
|
||||||
delete *(i->second);
|
i->second->reset();
|
||||||
*(i->second) = NULL;
|
m_update = true;
|
||||||
m_update = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,14 +169,13 @@ SocketMultiplexer::serviceThread(void*)
|
|||||||
JobCursor cursor = newCursor();
|
JobCursor cursor = newCursor();
|
||||||
JobCursor jobCursor = nextCursor(cursor);
|
JobCursor jobCursor = nextCursor(cursor);
|
||||||
while (jobCursor != m_socketJobs.end()) {
|
while (jobCursor != m_socketJobs.end()) {
|
||||||
ISocketMultiplexerJob* job = *jobCursor;
|
if (*jobCursor) {
|
||||||
if (job != NULL) {
|
pfd.m_socket = (*jobCursor)->getSocket();
|
||||||
pfd.m_socket = job->getSocket();
|
|
||||||
pfd.m_events = 0;
|
pfd.m_events = 0;
|
||||||
if (job->isReadable()) {
|
if ((*jobCursor)->isReadable()) {
|
||||||
pfd.m_events |= IArchNetwork::kPOLLIN;
|
pfd.m_events |= IArchNetwork::kPOLLIN;
|
||||||
}
|
}
|
||||||
if (job->isWritable()) {
|
if ((*jobCursor)->isWritable()) {
|
||||||
pfd.m_events |= IArchNetwork::kPOLLOUT;
|
pfd.m_events |= IArchNetwork::kPOLLOUT;
|
||||||
}
|
}
|
||||||
pfds.push_back(pfd);
|
pfds.push_back(pfd);
|
||||||
@@ -221,15 +216,16 @@ SocketMultiplexer::serviceThread(void*)
|
|||||||
IArchNetwork::kPOLLNVAL)) != 0);
|
IArchNetwork::kPOLLNVAL)) != 0);
|
||||||
|
|
||||||
// run job
|
// run job
|
||||||
ISocketMultiplexerJob* job = *jobCursor;
|
MultiplexerJobStatus status = (*jobCursor)->run(read, write, error);
|
||||||
ISocketMultiplexerJob* newJob = job->run(read, write, error);
|
|
||||||
|
|
||||||
// save job, if different
|
if (!status.continue_servicing) {
|
||||||
if (newJob != job) {
|
|
||||||
Lock lock(m_mutex);
|
Lock lock(m_mutex);
|
||||||
delete job;
|
jobCursor->reset();
|
||||||
*jobCursor = newJob;
|
m_update = true;
|
||||||
m_update = true;
|
} else if (status.new_job) {
|
||||||
|
Lock lock(m_mutex);
|
||||||
|
*jobCursor = std::move(status.new_job);
|
||||||
|
m_update = true;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -262,7 +258,7 @@ SocketMultiplexer::JobCursor
|
|||||||
SocketMultiplexer::newCursor()
|
SocketMultiplexer::newCursor()
|
||||||
{
|
{
|
||||||
Lock lock(m_mutex);
|
Lock lock(m_mutex);
|
||||||
return m_socketJobs.insert(m_socketJobs.begin(), m_cursorMark);
|
return m_socketJobs.insert(m_socketJobs.begin(), std::make_unique<CursorMultiplexerJob>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketMultiplexer::JobCursor
|
SocketMultiplexer::JobCursor
|
||||||
@@ -272,7 +268,7 @@ SocketMultiplexer::nextCursor(JobCursor cursor)
|
|||||||
JobCursor j = m_socketJobs.end();
|
JobCursor j = m_socketJobs.end();
|
||||||
JobCursor i = cursor;
|
JobCursor i = cursor;
|
||||||
while (++i != m_socketJobs.end()) {
|
while (++i != m_socketJobs.end()) {
|
||||||
if (*i != m_cursorMark) {
|
if (*i && !(*i)->isCursor()) {
|
||||||
// found a real job (as opposed to a cursor)
|
// found a real job (as opposed to a cursor)
|
||||||
j = i;
|
j = i;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "arch/IArchNetwork.h"
|
#include "arch/IArchNetwork.h"
|
||||||
#include "common/stdlist.h"
|
#include "common/stdlist.h"
|
||||||
#include "common/stdmap.h"
|
#include "common/stdmap.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class CondVar;
|
class CondVar;
|
||||||
@@ -41,7 +42,7 @@ public:
|
|||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
void addSocket(ISocket*, ISocketMultiplexerJob*);
|
void addSocket(ISocket*, std::unique_ptr<ISocketMultiplexerJob>&& job);
|
||||||
|
|
||||||
void removeSocket(ISocket*);
|
void removeSocket(ISocket*);
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// list of jobs. we use a list so we can safely iterate over it
|
// list of jobs. we use a list so we can safely iterate over it
|
||||||
// while other threads modify it.
|
// while other threads modify it.
|
||||||
typedef std::list<ISocketMultiplexerJob*> SocketJobs;
|
using SocketJobs = std::list<std::unique_ptr<ISocketMultiplexerJob>>;
|
||||||
typedef SocketJobs::iterator JobCursor;
|
typedef SocketJobs::iterator JobCursor;
|
||||||
typedef std::map<ISocket*, JobCursor> SocketJobMap;
|
typedef std::map<ISocket*, JobCursor> SocketJobMap;
|
||||||
|
|
||||||
@@ -106,6 +107,4 @@ private:
|
|||||||
|
|
||||||
SocketJobs m_socketJobs;
|
SocketJobs m_socketJobs;
|
||||||
SocketJobMap m_socketJobMap;
|
SocketJobMap m_socketJobMap;
|
||||||
ISocketMultiplexerJob*
|
|
||||||
m_cursorMark;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,10 +69,11 @@ TCPListenSocket::bind(const NetworkAddress& addr)
|
|||||||
ARCH->setReuseAddrOnSocket(m_socket, true);
|
ARCH->setReuseAddrOnSocket(m_socket, true);
|
||||||
ARCH->bindSocket(m_socket, addr.getAddress());
|
ARCH->bindSocket(m_socket, addr.getAddress());
|
||||||
ARCH->listenOnSocket(m_socket);
|
ARCH->listenOnSocket(m_socket);
|
||||||
m_socketMultiplexer->addSocket(this,
|
|
||||||
new TSocketMultiplexerMethodJob<TCPListenSocket>(
|
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
|
||||||
this, &TCPListenSocket::serviceListening,
|
this, &TCPListenSocket::serviceListening, m_socket, true, false);
|
||||||
m_socket, true, false));
|
|
||||||
|
m_socketMultiplexer->addSocket(this, std::move(new_job));
|
||||||
}
|
}
|
||||||
catch (XArchNetworkAddressInUse& e) {
|
catch (XArchNetworkAddressInUse& e) {
|
||||||
throw XSocketAddressInUse(e.what());
|
throw XSocketAddressInUse(e.what());
|
||||||
@@ -135,24 +136,22 @@ TCPListenSocket::accept()
|
|||||||
void
|
void
|
||||||
TCPListenSocket::setListeningJob()
|
TCPListenSocket::setListeningJob()
|
||||||
{
|
{
|
||||||
m_socketMultiplexer->addSocket(this,
|
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
|
||||||
new TSocketMultiplexerMethodJob<TCPListenSocket>(
|
this, &TCPListenSocket::serviceListening, m_socket, true, false);
|
||||||
this, &TCPListenSocket::serviceListening,
|
m_socketMultiplexer->addSocket(this, std::move(new_job));
|
||||||
m_socket, true, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus TCPListenSocket::serviceListening(ISocketMultiplexerJob* job,
|
||||||
TCPListenSocket::serviceListening(ISocketMultiplexerJob* job,
|
bool read, bool, bool error)
|
||||||
bool read, bool, bool error)
|
|
||||||
{
|
{
|
||||||
if (error) {
|
if (error) {
|
||||||
close();
|
close();
|
||||||
return NULL;
|
return {false, {}};
|
||||||
}
|
}
|
||||||
if (read) {
|
if (read) {
|
||||||
m_events->addEvent(Event(m_events->forIListenSocket().connecting(), this, NULL));
|
m_events->addEvent(Event(m_events->forIListenSocket().connecting(), this, NULL));
|
||||||
// stop polling on this socket until the client accepts
|
// stop polling on this socket until the client accepts
|
||||||
return NULL;
|
return {false, {}};
|
||||||
}
|
}
|
||||||
return job;
|
return {true, {}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "net/IListenSocket.h"
|
#include "net/IListenSocket.h"
|
||||||
|
#include "net/ISocketMultiplexerJob.h"
|
||||||
#include "arch/IArchNetwork.h"
|
#include "arch/IArchNetwork.h"
|
||||||
|
|
||||||
class Mutex;
|
class Mutex;
|
||||||
class ISocketMultiplexerJob;
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class SocketMultiplexer;
|
class SocketMultiplexer;
|
||||||
|
|
||||||
@@ -48,9 +48,7 @@ protected:
|
|||||||
void setListeningJob();
|
void setListeningJob();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus serviceListening(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
serviceListening(ISocketMultiplexerJob*,
|
|
||||||
bool, bool, bool);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ArchSocket m_socket;
|
ArchSocket m_socket;
|
||||||
|
|||||||
@@ -388,40 +388,42 @@ TCPSocket::doWrite()
|
|||||||
return kRetry;
|
return kRetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void TCPSocket::removeJob()
|
||||||
TCPSocket::setJob(ISocketMultiplexerJob* job)
|
|
||||||
{
|
{
|
||||||
// multiplexer will delete the old job
|
// multiplexer will delete the old job
|
||||||
if (job == NULL) {
|
m_socketMultiplexer->removeSocket(this);
|
||||||
m_socketMultiplexer->removeSocket(this);
|
}
|
||||||
}
|
|
||||||
else {
|
void TCPSocket::setJob(std::unique_ptr<ISocketMultiplexerJob>&& job)
|
||||||
m_socketMultiplexer->addSocket(this, job);
|
{
|
||||||
|
if (job.get() == nullptr) {
|
||||||
|
removeJob();
|
||||||
|
} else {
|
||||||
|
m_socketMultiplexer->addSocket(this, std::move(job));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
std::unique_ptr<ISocketMultiplexerJob> TCPSocket::newJob()
|
||||||
TCPSocket::newJob()
|
|
||||||
{
|
{
|
||||||
// note -- must have m_mutex locked on entry
|
// note -- must have m_mutex locked on entry
|
||||||
|
|
||||||
if (m_socket == NULL) {
|
if (m_socket == NULL) {
|
||||||
return NULL;
|
return {};
|
||||||
}
|
}
|
||||||
else if (!m_connected) {
|
else if (!m_connected) {
|
||||||
assert(!m_readable);
|
assert(!m_readable);
|
||||||
if (!(m_readable || m_writable)) {
|
if (!(m_readable || m_writable)) {
|
||||||
return NULL;
|
return {};
|
||||||
}
|
}
|
||||||
return new TSocketMultiplexerMethodJob<TCPSocket>(
|
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
|
||||||
this, &TCPSocket::serviceConnecting,
|
this, &TCPSocket::serviceConnecting,
|
||||||
m_socket, m_readable, m_writable);
|
m_socket, m_readable, m_writable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
|
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
|
||||||
return NULL;
|
return {};
|
||||||
}
|
}
|
||||||
return new TSocketMultiplexerMethodJob<TCPSocket>(
|
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
|
||||||
this, &TCPSocket::serviceConnected,
|
this, &TCPSocket::serviceConnected,
|
||||||
m_socket, m_readable,
|
m_socket, m_readable,
|
||||||
m_writable && (m_outputBuffer.getSize() > 0));
|
m_writable && (m_outputBuffer.getSize() > 0));
|
||||||
@@ -488,9 +490,7 @@ TCPSocket::onDisconnected()
|
|||||||
m_connected = false;
|
m_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus TCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bool, bool write, bool error)
|
||||||
TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
|
|
||||||
bool, bool write, bool error)
|
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
|
||||||
@@ -519,29 +519,36 @@ TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
|
|||||||
catch (XArchNetwork& e) {
|
catch (XArchNetwork& e) {
|
||||||
sendConnectionFailedEvent(e.what());
|
sendConnectionFailedEvent(e.what());
|
||||||
onDisconnected();
|
onDisconnected();
|
||||||
return newJob();
|
auto new_job = newJob();
|
||||||
|
if (new_job)
|
||||||
|
return {true, std::move(new_job)};
|
||||||
|
else
|
||||||
|
return {false, {}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
sendEvent(m_events->forIDataSocket().connected());
|
sendEvent(m_events->forIDataSocket().connected());
|
||||||
onConnected();
|
onConnected();
|
||||||
return newJob();
|
auto new_job = newJob();
|
||||||
|
if (new_job)
|
||||||
|
return {true, std::move(new_job)};
|
||||||
|
else
|
||||||
|
return {false, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
return job;
|
return {true, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
||||||
TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
bool read, bool write, bool error)
|
||||||
bool read, bool write, bool error)
|
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
sendEvent(m_events->forISocket().disconnected());
|
sendEvent(m_events->forISocket().disconnected());
|
||||||
onDisconnected();
|
onDisconnected();
|
||||||
return newJob();
|
return {true, newJob()};
|
||||||
}
|
}
|
||||||
|
|
||||||
EJobResult writeResult = kRetry;
|
EJobResult writeResult = kRetry;
|
||||||
@@ -594,10 +601,10 @@ TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (writeResult == kBreak || readResult == kBreak) {
|
if (writeResult == kBreak || readResult == kBreak) {
|
||||||
return NULL;
|
return {false, {}};
|
||||||
} else if (writeResult == kNew || readResult == kNew) {
|
} else if (writeResult == kNew || readResult == kNew) {
|
||||||
return newJob();
|
return {true, newJob()};
|
||||||
} else {
|
} else {
|
||||||
return job;
|
return {true, {}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "net/IDataSocket.h"
|
#include "net/IDataSocket.h"
|
||||||
|
#include "net/ISocketMultiplexerJob.h"
|
||||||
#include "io/StreamBuffer.h"
|
#include "io/StreamBuffer.h"
|
||||||
#include "mt/CondVar.h"
|
#include "mt/CondVar.h"
|
||||||
#include "mt/Mutex.h"
|
#include "mt/Mutex.h"
|
||||||
#include "arch/IArchNetwork.h"
|
#include "arch/IArchNetwork.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Mutex;
|
class Mutex;
|
||||||
class Thread;
|
class Thread;
|
||||||
class ISocketMultiplexerJob;
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class SocketMultiplexer;
|
class SocketMultiplexer;
|
||||||
|
|
||||||
@@ -59,8 +60,7 @@ public:
|
|||||||
virtual void connect(const NetworkAddress&);
|
virtual void connect(const NetworkAddress&);
|
||||||
|
|
||||||
|
|
||||||
virtual ISocketMultiplexerJob*
|
virtual std::unique_ptr<ISocketMultiplexerJob> newJob();
|
||||||
newJob();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum EJobResult {
|
enum EJobResult {
|
||||||
@@ -74,7 +74,8 @@ protected:
|
|||||||
virtual EJobResult doRead();
|
virtual EJobResult doRead();
|
||||||
virtual EJobResult doWrite();
|
virtual EJobResult doWrite();
|
||||||
|
|
||||||
void setJob(ISocketMultiplexerJob*);
|
void removeJob();
|
||||||
|
void setJob(std::unique_ptr<ISocketMultiplexerJob>&& job);
|
||||||
|
|
||||||
bool isReadable() { return m_readable; }
|
bool isReadable() { return m_readable; }
|
||||||
bool isWritable() { return m_writable; }
|
bool isWritable() { return m_writable; }
|
||||||
@@ -93,12 +94,8 @@ private:
|
|||||||
void onOutputShutdown();
|
void onOutputShutdown();
|
||||||
void onDisconnected();
|
void onDisconnected();
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
MultiplexerJobStatus serviceConnecting(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
serviceConnecting(ISocketMultiplexerJob*,
|
MultiplexerJobStatus serviceConnected(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
bool, bool, bool);
|
|
||||||
ISocketMultiplexerJob*
|
|
||||||
serviceConnected(ISocketMultiplexerJob*,
|
|
||||||
bool, bool, bool);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_readable;
|
bool m_readable;
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ A socket multiplexer job class that invokes a member function.
|
|||||||
template <class T>
|
template <class T>
|
||||||
class TSocketMultiplexerMethodJob : public ISocketMultiplexerJob {
|
class TSocketMultiplexerMethodJob : public ISocketMultiplexerJob {
|
||||||
public:
|
public:
|
||||||
typedef ISocketMultiplexerJob*
|
using Method = MultiplexerJobStatus (T::*)(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
(T::*Method)(ISocketMultiplexerJob*, bool, bool, bool);
|
|
||||||
|
|
||||||
//! run() invokes \c object->method(arg)
|
//! run() invokes \c object->method(arg)
|
||||||
TSocketMultiplexerMethodJob(T* object, Method method,
|
TSocketMultiplexerMethodJob(T* object, Method method,
|
||||||
@@ -37,11 +36,10 @@ public:
|
|||||||
virtual ~TSocketMultiplexerMethodJob();
|
virtual ~TSocketMultiplexerMethodJob();
|
||||||
|
|
||||||
// IJob overrides
|
// IJob overrides
|
||||||
virtual ISocketMultiplexerJob*
|
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) override;
|
||||||
run(bool readable, bool writable, bool error);
|
virtual ArchSocket getSocket() const override;
|
||||||
virtual ArchSocket getSocket() const;
|
virtual bool isReadable() const override;
|
||||||
virtual bool isReadable() const;
|
virtual bool isWritable() const override;
|
||||||
virtual bool isWritable() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* m_object;
|
T* m_object;
|
||||||
@@ -74,14 +72,12 @@ TSocketMultiplexerMethodJob<T>::~TSocketMultiplexerMethodJob()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline
|
inline MultiplexerJobStatus TSocketMultiplexerMethodJob<T>::run(bool read, bool write, bool error)
|
||||||
ISocketMultiplexerJob*
|
|
||||||
TSocketMultiplexerMethodJob<T>::run(bool read, bool write, bool error)
|
|
||||||
{
|
{
|
||||||
if (m_object != NULL) {
|
if (m_object != NULL) {
|
||||||
return (m_object->*m_method)(this, read, write, error);
|
return (m_object->*m_method)(this, read, write, error);
|
||||||
}
|
}
|
||||||
return NULL;
|
return {false, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "base/IEventQueue.h"
|
#include "base/IEventQueue.h"
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
// these are only defined when WINVER >= 0x0500
|
// these are only defined when WINVER >= 0x0500
|
||||||
#if !defined(SPI_GETMOUSESPEED)
|
#if !defined(SPI_GETMOUSESPEED)
|
||||||
@@ -45,6 +46,10 @@
|
|||||||
#define SPI_GETSCREENSAVERRUNNING 114
|
#define SPI_GETSCREENSAVERRUNNING 114
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MOUSEEVENTF_HWHEEL)
|
||||||
|
#define MOUSEEVENTF_HWHEEL 0x1000
|
||||||
|
#endif
|
||||||
|
|
||||||
// X button stuff
|
// X button stuff
|
||||||
#if !defined(WM_XBUTTONDOWN)
|
#if !defined(WM_XBUTTONDOWN)
|
||||||
#define WM_XBUTTONDOWN 0x020B
|
#define WM_XBUTTONDOWN 0x020B
|
||||||
@@ -296,12 +301,12 @@ MSWindowsDesks::fakeMouseButton(ButtonID button, bool press)
|
|||||||
flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
|
flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kButtonExtra0 + 0:
|
case kButtonExtra0:
|
||||||
data = XBUTTON1;
|
data = XBUTTON1;
|
||||||
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kButtonExtra0 + 1:
|
case kButtonExtra1:
|
||||||
data = XBUTTON2;
|
data = XBUTTON2;
|
||||||
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
||||||
break;
|
break;
|
||||||
@@ -686,10 +691,12 @@ MSWindowsDesks::deskThread(void* vdesk)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BARRIER_MSG_FAKE_WHEEL:
|
case BARRIER_MSG_FAKE_WHEEL:
|
||||||
// XXX -- add support for x-axis scrolling
|
|
||||||
if (msg.lParam != 0) {
|
if (msg.lParam != 0) {
|
||||||
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam, 0);
|
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam, 0);
|
||||||
}
|
}
|
||||||
|
else if (IsWindowsVistaOrGreater() && msg.wParam != 0) {
|
||||||
|
mouse_event(MOUSEEVENTF_HWHEEL, 0, 0, (DWORD)msg.wParam, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BARRIER_MSG_CURSOR_POS: {
|
case BARRIER_MSG_CURSOR_POS: {
|
||||||
|
|||||||
@@ -25,6 +25,10 @@
|
|||||||
#include "common/DataDirectories.h"
|
#include "common/DataDirectories.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
|
|
||||||
|
#ifndef WM_MOUSEHWHEEL
|
||||||
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// debugging compile flag. when not zero the server doesn't grab
|
// debugging compile flag. when not zero the server doesn't grab
|
||||||
// the keyboard when the mouse leaves the server screen. this
|
// the keyboard when the mouse leaves the server screen. this
|
||||||
@@ -473,6 +477,13 @@ mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
|
|||||||
}
|
}
|
||||||
return (g_mode == kHOOK_RELAY_EVENTS);
|
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||||
|
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
|
// relay event
|
||||||
|
PostThreadMessage(g_threadID, BARRIER_MSG_MOUSE_WHEEL, 0, data);
|
||||||
|
}
|
||||||
|
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||||
|
|
||||||
case WM_NCMOUSEMOVE:
|
case WM_NCMOUSEMOVE:
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
if (g_mode == kHOOK_RELAY_EVENTS) {
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
|
|||||||
@@ -952,9 +952,9 @@ MSWindowsScreen::updateButtons()
|
|||||||
m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0);
|
m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0);
|
||||||
m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0);
|
m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0);
|
||||||
m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0);
|
m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0);
|
||||||
m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) &&
|
m_buttons[kButtonExtra0] = (numButtons >= 4) &&
|
||||||
(GetKeyState(VK_XBUTTON1) < 0);
|
(GetKeyState(VK_XBUTTON1) < 0);
|
||||||
m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) &&
|
m_buttons[kButtonExtra1] = (numButtons >= 5) &&
|
||||||
(GetKeyState(VK_XBUTTON2) < 0);
|
(GetKeyState(VK_XBUTTON2) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,8 +1007,7 @@ MSWindowsScreen::onPreDispatchPrimary(HWND,
|
|||||||
static_cast<SInt32>(lParam));
|
static_cast<SInt32>(lParam));
|
||||||
|
|
||||||
case BARRIER_MSG_MOUSE_WHEEL:
|
case BARRIER_MSG_MOUSE_WHEEL:
|
||||||
// XXX -- support x-axis scrolling
|
return onMouseWheel(static_cast<SInt32>(lParam), static_cast<SInt32>(wParam));
|
||||||
return onMouseWheel(0, static_cast<SInt32>(wParam));
|
|
||||||
|
|
||||||
case BARRIER_MSG_PRE_WARP:
|
case BARRIER_MSG_PRE_WARP:
|
||||||
{
|
{
|
||||||
@@ -1670,13 +1669,13 @@ MSWindowsScreen::mapButtonFromEvent(WPARAM msg, LPARAM button) const
|
|||||||
switch (button) {
|
switch (button) {
|
||||||
case XBUTTON1:
|
case XBUTTON1:
|
||||||
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) {
|
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) {
|
||||||
return kButtonExtra0 + 0;
|
return kButtonExtra0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XBUTTON2:
|
case XBUTTON2:
|
||||||
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) {
|
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) {
|
||||||
return kButtonExtra0 + 1;
|
return kButtonExtra1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ private:
|
|||||||
HotKeyToIDMap m_hotKeyToIDMap;
|
HotKeyToIDMap m_hotKeyToIDMap;
|
||||||
|
|
||||||
// map of button state
|
// map of button state
|
||||||
bool m_buttons[1 + kButtonExtra0 + 1];
|
bool m_buttons[NumButtonIDs];
|
||||||
|
|
||||||
// the system shows the mouse cursor when an internal display count
|
// the system shows the mouse cursor when an internal display count
|
||||||
// is >= 0. this count is maintained per application but there's
|
// is >= 0. this count is maintained per application but there's
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
void sendClipboardEvent(Event::Type type, ClipboardID id) const;
|
void sendClipboardEvent(Event::Type type, ClipboardID id) const;
|
||||||
|
|
||||||
// message handlers
|
// message handlers
|
||||||
bool onMouseMove(SInt32 mx, SInt32 my);
|
bool onMouseMove(CGFloat mx, CGFloat my);
|
||||||
// mouse button handler. pressed is true if this is a mousedown
|
// mouse button handler. pressed is true if this is a mousedown
|
||||||
// event, false if it is a mouseup event. macButton is the index
|
// event, false if it is a mouseup event. macButton is the index
|
||||||
// of the button pressed using the mac button mapping.
|
// of the button pressed using the mac button mapping.
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ OSXScreen::constructMouseButtonEventMap()
|
|||||||
{kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown},
|
{kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown},
|
||||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||||
|
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}
|
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1076,20 +1077,20 @@ OSXScreen::handleSystemEvent(const Event& event, void*)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OSXScreen::onMouseMove(SInt32 mx, SInt32 my)
|
OSXScreen::onMouseMove(CGFloat mx, CGFloat my)
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG2 "mouse move %+d,%+d", mx, my));
|
LOG((CLOG_DEBUG2 "mouse move %+f,%+f", mx, my));
|
||||||
|
|
||||||
SInt32 x = mx - m_xCursor;
|
CGFloat x = mx - m_xCursor;
|
||||||
SInt32 y = my - m_yCursor;
|
CGFloat y = my - m_yCursor;
|
||||||
|
|
||||||
if ((x == 0 && y == 0) || (mx == m_xCenter && mx == m_yCenter)) {
|
if ((x == 0 && y == 0) || (mx == m_xCenter && mx == m_yCenter)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save position to compute delta of next motion
|
// save position to compute delta of next motion
|
||||||
m_xCursor = mx;
|
m_xCursor = (SInt32)mx;
|
||||||
m_yCursor = my;
|
m_yCursor = (SInt32)my;
|
||||||
|
|
||||||
if (m_isOnScreen) {
|
if (m_isOnScreen) {
|
||||||
// motion on primary screen
|
// motion on primary screen
|
||||||
@@ -1118,7 +1119,21 @@ OSXScreen::onMouseMove(SInt32 mx, SInt32 my)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// send motion
|
// send motion
|
||||||
sendEvent(m_events->forIPrimaryScreen().motionOnSecondary(), MotionInfo::alloc(x, y));
|
// Accumulate together the move into the running total
|
||||||
|
static CGFloat m_xFractionalMove = 0;
|
||||||
|
static CGFloat m_yFractionalMove = 0;
|
||||||
|
|
||||||
|
m_xFractionalMove += x;
|
||||||
|
m_yFractionalMove += y;
|
||||||
|
|
||||||
|
// Return the integer part
|
||||||
|
SInt32 intX = (SInt32)m_xFractionalMove;
|
||||||
|
SInt32 intY = (SInt32)m_yFractionalMove;
|
||||||
|
|
||||||
|
// And keep only the fractional part
|
||||||
|
m_xFractionalMove -= intX;
|
||||||
|
m_yFractionalMove -= intY;
|
||||||
|
sendEvent(m_events->forIPrimaryScreen().motionOnSecondary(), MotionInfo::alloc(intX, intY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ XWindowsScreen::XWindowsScreen(
|
|||||||
IEventQueue* events) :
|
IEventQueue* events) :
|
||||||
m_isPrimary(isPrimary),
|
m_isPrimary(isPrimary),
|
||||||
m_mouseScrollDelta(mouseScrollDelta),
|
m_mouseScrollDelta(mouseScrollDelta),
|
||||||
m_accumulatedScroll(0),
|
m_x_accumulatedScroll(0),
|
||||||
|
m_y_accumulatedScroll(0),
|
||||||
m_display(NULL),
|
m_display(NULL),
|
||||||
m_root(None),
|
m_root(None),
|
||||||
m_window(None),
|
m_window(None),
|
||||||
@@ -829,35 +830,37 @@ XWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
XWindowsScreen::fakeMouseWheel(SInt32, SInt32 yDelta) const
|
XWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
|
||||||
{
|
{
|
||||||
// XXX -- support x-axis scrolling
|
int numEvents;
|
||||||
if (yDelta == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numEvents = accumulateMouseScroll(yDelta);
|
if ((!xDelta && !yDelta) || (xDelta && yDelta)) {
|
||||||
|
// Invalid scrolling inputs
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// choose button depending on rotation direction
|
// 4, 5, 6, 7
|
||||||
const unsigned int xButton = mapButtonToX(static_cast<ButtonID>(
|
// up, down, left, right
|
||||||
(numEvents >= 0) ? -1 : -2));
|
unsigned int xButton;
|
||||||
if (xButton == 0) {
|
|
||||||
// If we get here, then the XServer does not support the scroll
|
if (yDelta) { // vertical scroll
|
||||||
// wheel buttons, so send PageUp/PageDown keystrokes instead.
|
numEvents = y_accumulateMouseScroll(yDelta);
|
||||||
// Patch by Tom Chadwick.
|
if (numEvents >= 0) {
|
||||||
KeyCode keycode = 0;
|
xButton = 4; // up
|
||||||
if (yDelta >= 0) {
|
}
|
||||||
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Up);
|
else {
|
||||||
}
|
xButton = 5; // down
|
||||||
else {
|
}
|
||||||
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Down);
|
}
|
||||||
}
|
else { // horizontal scroll
|
||||||
if (keycode != 0) {
|
numEvents = x_accumulateMouseScroll(xDelta);
|
||||||
m_impl->XTestFakeKeyEvent(m_display, keycode, True, CurrentTime);
|
if (numEvents >= 0) {
|
||||||
m_impl->XTestFakeKeyEvent(m_display, keycode, False, CurrentTime);
|
xButton = 7; // right
|
||||||
}
|
}
|
||||||
return;
|
else {
|
||||||
}
|
xButton = 6; // left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
numEvents = std::abs(numEvents);
|
numEvents = std::abs(numEvents);
|
||||||
|
|
||||||
@@ -1540,7 +1543,14 @@ XWindowsScreen::onMouseRelease(const XButtonEvent& xbutton)
|
|||||||
// wheel backward (toward user)
|
// wheel backward (toward user)
|
||||||
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(0, -120));
|
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(0, -120));
|
||||||
}
|
}
|
||||||
// XXX -- support x-axis scrolling
|
else if (xbutton.button == 6) {
|
||||||
|
// wheel left
|
||||||
|
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(-120, 0));
|
||||||
|
}
|
||||||
|
else if (xbutton.button == 7) {
|
||||||
|
// wheel right
|
||||||
|
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(120, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1613,11 +1623,20 @@ XWindowsScreen::onMouseMove(const XMotionEvent& xmotion)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
XWindowsScreen::accumulateMouseScroll(SInt32 yDelta) const
|
XWindowsScreen::x_accumulateMouseScroll(SInt32 xDelta) const
|
||||||
{
|
{
|
||||||
m_accumulatedScroll += yDelta;
|
m_x_accumulatedScroll += xDelta;
|
||||||
int numEvents = m_accumulatedScroll / m_mouseScrollDelta;
|
int numEvents = m_x_accumulatedScroll / m_mouseScrollDelta;
|
||||||
m_accumulatedScroll -= numEvents * m_mouseScrollDelta;
|
m_x_accumulatedScroll -= numEvents * m_mouseScrollDelta;
|
||||||
|
return numEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
XWindowsScreen::y_accumulateMouseScroll(SInt32 yDelta) const
|
||||||
|
{
|
||||||
|
m_y_accumulatedScroll += yDelta;
|
||||||
|
int numEvents = m_y_accumulatedScroll / m_mouseScrollDelta;
|
||||||
|
m_y_accumulatedScroll -= numEvents * m_mouseScrollDelta;
|
||||||
return numEvents;
|
return numEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1840,19 +1859,19 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
|
|||||||
{
|
{
|
||||||
unsigned int button = event->button;
|
unsigned int button = event->button;
|
||||||
|
|
||||||
// first three buttons map to 1, 2, 3 (kButtonLeft, Middle, Right)
|
// http://xahlee.info/linux/linux_x11_mouse_button_number.html
|
||||||
if (button >= 1 && button <= 3) {
|
// and the program `xev`
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case 1: case 2: case 3: // kButtonLeft, Middle, Right
|
||||||
return static_cast<ButtonID>(button);
|
return static_cast<ButtonID>(button);
|
||||||
}
|
case 4: case 5: case 6: case 7: // scroll up, down, left, right -- ignored here
|
||||||
|
return kButtonNone;
|
||||||
// buttons 4 and 5 are ignored here. they're used for the wheel.
|
case 8: // mouse button 4
|
||||||
// buttons 6, 7, etc and up map to 4, 5, etc.
|
return kButtonExtra0;
|
||||||
else if (button >= 6) {
|
case 9: // mouse button 5
|
||||||
return static_cast<ButtonID>(button - 2);
|
return kButtonExtra1;
|
||||||
}
|
default: // unknown button
|
||||||
|
|
||||||
// unknown button
|
|
||||||
else {
|
|
||||||
return kButtonNone;
|
return kButtonNone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1860,30 +1879,17 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
|
|||||||
unsigned int
|
unsigned int
|
||||||
XWindowsScreen::mapButtonToX(ButtonID id) const
|
XWindowsScreen::mapButtonToX(ButtonID id) const
|
||||||
{
|
{
|
||||||
// map button -1 to button 4 (+wheel)
|
switch (id)
|
||||||
if (id == static_cast<ButtonID>(-1)) {
|
{
|
||||||
id = 4;
|
case kButtonLeft: case kButtonMiddle: case kButtonRight:
|
||||||
}
|
return id;
|
||||||
|
case kButtonExtra0:
|
||||||
// map button -2 to button 5 (-wheel)
|
return 8;
|
||||||
else if (id == static_cast<ButtonID>(-2)) {
|
case kButtonExtra1:
|
||||||
id = 5;
|
return 9;
|
||||||
}
|
default:
|
||||||
|
|
||||||
// map buttons 4, 5, etc. to 6, 7, etc. to make room for buttons
|
|
||||||
// 4 and 5 used to simulate the mouse wheel.
|
|
||||||
else if (id >= 4) {
|
|
||||||
id += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check button is in legal range
|
|
||||||
if (id < 1 || id > m_buttons.size()) {
|
|
||||||
// out of range
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// map button
|
|
||||||
return static_cast<unsigned int>(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ private:
|
|||||||
|
|
||||||
// Returns the number of scroll events needed after the current delta has
|
// Returns the number of scroll events needed after the current delta has
|
||||||
// been taken into account
|
// been taken into account
|
||||||
int accumulateMouseScroll(SInt32 yDelta) const;
|
int x_accumulateMouseScroll(SInt32 xDelta) const;
|
||||||
|
int y_accumulateMouseScroll(SInt32 yDelta) const;
|
||||||
|
|
||||||
bool detectXI2();
|
bool detectXI2();
|
||||||
#ifdef HAVE_XI2
|
#ifdef HAVE_XI2
|
||||||
@@ -183,10 +184,11 @@ private:
|
|||||||
// The size of a smallest supported scroll event, in points
|
// The size of a smallest supported scroll event, in points
|
||||||
int m_mouseScrollDelta;
|
int m_mouseScrollDelta;
|
||||||
|
|
||||||
// Accumulates scrolls of less than m_mouseScrollDelta across multiple
|
// Accumulates scrolls of less than m_?_mouseScrollDelta across multiple
|
||||||
// scroll events. We dispatch a scroll event whenever the accumulated scroll
|
// scroll events. We dispatch a scroll event whenever the accumulated scroll
|
||||||
// becomes larger than m_mouseScrollDelta
|
// becomes larger than m_?_mouseScrollDelta
|
||||||
mutable int m_accumulatedScroll;
|
mutable int m_x_accumulatedScroll;
|
||||||
|
mutable int m_y_accumulatedScroll;
|
||||||
|
|
||||||
Display* m_display;
|
Display* m_display;
|
||||||
Window m_root;
|
Window m_root;
|
||||||
|
|||||||
Reference in New Issue
Block a user